blob: 7da3c19a89a4bc09aaca93b384558796d978e07b [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
Brianb7978af2007-01-09 19:17:17 -07003 * Version: 6.5.3
Jouk Jansen40322e12004-04-05 08:50:36 +00004 *
Brianb7978af2007-01-09 19:17:17 -07005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
Jouk Jansen40322e12004-04-05 08:50:36 +00006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#define DEBUG_PARSING 0
26
27/**
28 * \file arbprogparse.c
29 * ARB_*_program parser core
30 * \author Karl Rasche
31 */
32
Jouk Jansen40322e12004-04-05 08:50:36 +000033#include "glheader.h"
Jouk Jansen40322e12004-04-05 08:50:36 +000034#include "imports.h"
Jouk Jansen40322e12004-04-05 08:50:36 +000035#include "arbprogparse.h"
36#include "grammar_mesa.h"
Brian Paul32df89e2005-10-29 18:26:43 +000037#include "program.h"
Brianc0551f02006-12-14 15:02:37 -070038#include "prog_parameter.h"
39#include "prog_statevars.h"
Brian Paul8c41a142005-11-19 15:36:28 +000040#include "context.h"
Brian Paul6211a142006-08-24 23:37:13 +000041#include "macros.h"
Brian Paul8c41a142005-11-19 15:36:28 +000042#include "mtypes.h"
Brianc0551f02006-12-14 15:02:37 -070043#include "prog_instruction.h"
Brian Paul8c41a142005-11-19 15:36:28 +000044
45
Brian Paul6211a142006-08-24 23:37:13 +000046/* For ARB programs, use the NV instruction limits */
47#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
48 MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
Brian Paul8c41a142005-11-19 15:36:28 +000049
50
51/**
52 * This is basically a union of the vertex_program and fragment_program
53 * structs that we can use to parse the program into
54 *
55 * XXX we can probably get rid of this entirely someday.
56 */
57struct arb_program
58{
Brian Paul122629f2006-07-20 16:49:57 +000059 struct gl_program Base;
Brian Paul8c41a142005-11-19 15:36:28 +000060
61 GLuint Position; /* Just used for error reporting while parsing */
62 GLuint MajorVersion;
63 GLuint MinorVersion;
64
65 /* ARB_vertex_progmra options */
66 GLboolean HintPositionInvariant;
67
68 /* ARB_fragment_progmra options */
69 GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */
70 GLenum FogOption; /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */
71
72 /* ARB_fragment_program specifics */
73 GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];
74 GLuint NumAluInstructions;
75 GLuint NumTexInstructions;
76 GLuint NumTexIndirections;
77
78 GLboolean UsesKill;
79};
80
Ian Romanick9bdfee32005-07-18 12:31:24 +000081
Brian Paula6c423d2004-08-25 15:59:48 +000082
Jouk Jansen40322e12004-04-05 08:50:36 +000083/* TODO:
84 * Fragment Program Stuff:
85 * -----------------------------------------------------
86 *
87 * - things from Michal's email
88 * + overflow on atoi
89 * + not-overflowing floats (don't use parse_integer..)
90 * + can remove range checking in arbparse.c
91 *
92 * - check all limits of number of various variables
93 * + parameters
94 *
95 * - test! test! test!
96 *
97 * Vertex Program Stuff:
98 * -----------------------------------------------------
99 * - Optimize param array usage and count limits correctly, see spec,
100 * section 2.14.3.7
101 * + Record if an array is reference absolutly or relatively (or both)
102 * + For absolute arrays, store a bitmap of accesses
103 * + For single parameters, store an access flag
104 * + After parsing, make a parameter cleanup and merging pass, where
105 * relative arrays are layed out first, followed by abs arrays, and
106 * finally single state.
107 * + Remap offsets for param src and dst registers
108 * + Now we can properly count parameter usage
109 *
110 * - Multiple state binding errors in param arrays (see spec, just before
111 * section 2.14.3.3)
112 * - grep for XXX
113 *
114 * Mesa Stuff
115 * -----------------------------------------------------
116 * - User clipping planes vs. PositionInvariant
117 * - Is it sufficient to just multiply by the mvp to transform in the
118 * PositionInvariant case? Or do we need something more involved?
119 *
120 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
121 * - fetch state listed in program_parameters list
122 * + WTF should this go???
123 * + currently in nvvertexec.c and s_nvfragprog.c
124 *
125 * - allow for multiple address registers (and fetch address regs properly)
126 *
127 * Cosmetic Stuff
128 * -----------------------------------------------------
129 * - remove any leftover unused grammer.c stuff (dict_ ?)
130 * - fix grammer.c error handling so its not static
131 * - #ifdef around stuff pertaining to extentions
132 *
133 * Outstanding Questions:
134 * -----------------------------------------------------
135 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
136 * what gets hacked off because of this:
137 * + VERTEX_ATTRIB_MATRIXINDEX
138 * + VERTEX_ATTRIB_WEIGHT
139 * + MATRIX_MODELVIEW
140 * + MATRIX_PALETTE
141 *
142 * - When can we fetch env/local params from their own register files, and
143 * when to we have to fetch them into the main state register file?
144 * (think arrays)
145 *
146 * Grammar Changes:
147 * -----------------------------------------------------
148 */
149
150/* Changes since moving the file to shader directory
151
1522004-III-4 ------------------------------------------------------------
153- added #include "grammar_mesa.h"
154- removed grammar specific code part (it resides now in grammar.c)
155- added GL_ARB_fragment_program_shadow tokens
156- modified #include "arbparse_syn.h"
157- major changes inside _mesa_parse_arb_program()
158- check the program string for '\0' characters
159- copy the program string to a one-byte-longer location to have
160 it null-terminated
161- position invariance test (not writing to result.position) moved
162 to syntax part
163*/
164
165typedef GLubyte *production;
166
Brian Paul11a54c32006-11-15 19:54:25 +0000167
Jouk Jansen40322e12004-04-05 08:50:36 +0000168/**
169 * This is the text describing the rules to parse the grammar
170 */
Brian Paul11a54c32006-11-15 19:54:25 +0000171LONGSTRING static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000172#include "arbprogram_syn.h"
173;
174
175/**
176 * These should match up with the values defined in arbprogram.syn
177 */
178
179/*
180 Changes:
181 - changed and merged V_* and F_* opcode values to OP_*.
182 - added GL_ARB_fragment_program_shadow specific tokens (michal)
183*/
Ian Romanickbb372f12007-05-16 15:34:22 -0700184#define REVISION 0x0a
Jouk Jansen40322e12004-04-05 08:50:36 +0000185
186/* program type */
187#define FRAGMENT_PROGRAM 0x01
188#define VERTEX_PROGRAM 0x02
189
190/* program section */
191#define OPTION 0x01
192#define INSTRUCTION 0x02
193#define DECLARATION 0x03
194#define END 0x04
195
Michal Krolb80bc052004-10-21 14:09:54 +0000196/* GL_ARB_fragment_program option */
197#define ARB_PRECISION_HINT_FASTEST 0x00
198#define ARB_PRECISION_HINT_NICEST 0x01
199#define ARB_FOG_EXP 0x02
200#define ARB_FOG_EXP2 0x03
201#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000202
Michal Krolb80bc052004-10-21 14:09:54 +0000203/* GL_ARB_vertex_program option */
204#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000205
Michal Krolb80bc052004-10-21 14:09:54 +0000206/* GL_ARB_fragment_program_shadow option */
207#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000208
Michal Krolb80bc052004-10-21 14:09:54 +0000209/* GL_ARB_draw_buffers option */
210#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000211
Ian Romanickbb372f12007-05-16 15:34:22 -0700212/* GL_MESA_texture_array option */
213#define MESA_TEXTURE_ARRAY 0x08
214
Jouk Jansen40322e12004-04-05 08:50:36 +0000215/* GL_ARB_fragment_program instruction class */
216#define OP_ALU_INST 0x00
217#define OP_TEX_INST 0x01
218
219/* GL_ARB_vertex_program instruction class */
220/* OP_ALU_INST */
221
222/* GL_ARB_fragment_program instruction type */
223#define OP_ALU_VECTOR 0x00
224#define OP_ALU_SCALAR 0x01
225#define OP_ALU_BINSC 0x02
226#define OP_ALU_BIN 0x03
227#define OP_ALU_TRI 0x04
228#define OP_ALU_SWZ 0x05
229#define OP_TEX_SAMPLE 0x06
230#define OP_TEX_KIL 0x07
231
232/* GL_ARB_vertex_program instruction type */
233#define OP_ALU_ARL 0x08
234/* OP_ALU_VECTOR */
235/* OP_ALU_SCALAR */
236/* OP_ALU_BINSC */
237/* OP_ALU_BIN */
238/* OP_ALU_TRI */
239/* OP_ALU_SWZ */
240
241/* GL_ARB_fragment_program instruction code */
242#define OP_ABS 0x00
243#define OP_ABS_SAT 0x1B
244#define OP_FLR 0x09
245#define OP_FLR_SAT 0x26
246#define OP_FRC 0x0A
247#define OP_FRC_SAT 0x27
248#define OP_LIT 0x0C
249#define OP_LIT_SAT 0x2A
250#define OP_MOV 0x11
251#define OP_MOV_SAT 0x30
252#define OP_COS 0x1F
253#define OP_COS_SAT 0x20
254#define OP_EX2 0x07
255#define OP_EX2_SAT 0x25
256#define OP_LG2 0x0B
257#define OP_LG2_SAT 0x29
258#define OP_RCP 0x14
259#define OP_RCP_SAT 0x33
260#define OP_RSQ 0x15
261#define OP_RSQ_SAT 0x34
262#define OP_SIN 0x38
263#define OP_SIN_SAT 0x39
264#define OP_SCS 0x35
265#define OP_SCS_SAT 0x36
266#define OP_POW 0x13
267#define OP_POW_SAT 0x32
268#define OP_ADD 0x01
269#define OP_ADD_SAT 0x1C
270#define OP_DP3 0x03
271#define OP_DP3_SAT 0x21
272#define OP_DP4 0x04
273#define OP_DP4_SAT 0x22
274#define OP_DPH 0x05
275#define OP_DPH_SAT 0x23
276#define OP_DST 0x06
277#define OP_DST_SAT 0x24
278#define OP_MAX 0x0F
279#define OP_MAX_SAT 0x2E
280#define OP_MIN 0x10
281#define OP_MIN_SAT 0x2F
282#define OP_MUL 0x12
283#define OP_MUL_SAT 0x31
284#define OP_SGE 0x16
285#define OP_SGE_SAT 0x37
286#define OP_SLT 0x17
287#define OP_SLT_SAT 0x3A
288#define OP_SUB 0x18
289#define OP_SUB_SAT 0x3B
290#define OP_XPD 0x1A
291#define OP_XPD_SAT 0x43
292#define OP_CMP 0x1D
293#define OP_CMP_SAT 0x1E
294#define OP_LRP 0x2B
295#define OP_LRP_SAT 0x2C
296#define OP_MAD 0x0E
297#define OP_MAD_SAT 0x2D
298#define OP_SWZ 0x19
299#define OP_SWZ_SAT 0x3C
300#define OP_TEX 0x3D
301#define OP_TEX_SAT 0x3E
302#define OP_TXB 0x3F
303#define OP_TXB_SAT 0x40
304#define OP_TXP 0x41
305#define OP_TXP_SAT 0x42
306#define OP_KIL 0x28
307
308/* GL_ARB_vertex_program instruction code */
309#define OP_ARL 0x02
310/* OP_ABS */
311/* OP_FLR */
312/* OP_FRC */
313/* OP_LIT */
314/* OP_MOV */
315/* OP_EX2 */
316#define OP_EXP 0x08
317/* OP_LG2 */
318#define OP_LOG 0x0D
319/* OP_RCP */
320/* OP_RSQ */
321/* OP_POW */
322/* OP_ADD */
323/* OP_DP3 */
324/* OP_DP4 */
325/* OP_DPH */
326/* OP_DST */
327/* OP_MAX */
328/* OP_MIN */
329/* OP_MUL */
330/* OP_SGE */
331/* OP_SLT */
332/* OP_SUB */
333/* OP_XPD */
334/* OP_MAD */
335/* OP_SWZ */
336
337/* fragment attribute binding */
338#define FRAGMENT_ATTRIB_COLOR 0x01
339#define FRAGMENT_ATTRIB_TEXCOORD 0x02
340#define FRAGMENT_ATTRIB_FOGCOORD 0x03
341#define FRAGMENT_ATTRIB_POSITION 0x04
342
343/* vertex attribute binding */
344#define VERTEX_ATTRIB_POSITION 0x01
345#define VERTEX_ATTRIB_WEIGHT 0x02
346#define VERTEX_ATTRIB_NORMAL 0x03
347#define VERTEX_ATTRIB_COLOR 0x04
348#define VERTEX_ATTRIB_FOGCOORD 0x05
349#define VERTEX_ATTRIB_TEXCOORD 0x06
350#define VERTEX_ATTRIB_MATRIXINDEX 0x07
351#define VERTEX_ATTRIB_GENERIC 0x08
352
353/* fragment result binding */
354#define FRAGMENT_RESULT_COLOR 0x01
355#define FRAGMENT_RESULT_DEPTH 0x02
356
357/* vertex result binding */
358#define VERTEX_RESULT_POSITION 0x01
359#define VERTEX_RESULT_COLOR 0x02
360#define VERTEX_RESULT_FOGCOORD 0x03
361#define VERTEX_RESULT_POINTSIZE 0x04
362#define VERTEX_RESULT_TEXCOORD 0x05
363
364/* texture target */
365#define TEXTARGET_1D 0x01
366#define TEXTARGET_2D 0x02
367#define TEXTARGET_3D 0x03
368#define TEXTARGET_RECT 0x04
369#define TEXTARGET_CUBE 0x05
370/* GL_ARB_fragment_program_shadow */
371#define TEXTARGET_SHADOW1D 0x06
372#define TEXTARGET_SHADOW2D 0x07
373#define TEXTARGET_SHADOWRECT 0x08
Ian Romanickbb372f12007-05-16 15:34:22 -0700374/* GL_MESA_texture_array */
375#define TEXTARGET_1D_ARRAY 0x09
376#define TEXTARGET_2D_ARRAY 0x0a
Jouk Jansen40322e12004-04-05 08:50:36 +0000377
378/* face type */
379#define FACE_FRONT 0x00
380#define FACE_BACK 0x01
381
382/* color type */
383#define COLOR_PRIMARY 0x00
384#define COLOR_SECONDARY 0x01
385
386/* component */
387#define COMPONENT_X 0x00
388#define COMPONENT_Y 0x01
389#define COMPONENT_Z 0x02
390#define COMPONENT_W 0x03
391#define COMPONENT_0 0x04
392#define COMPONENT_1 0x05
393
394/* array index type */
395#define ARRAY_INDEX_ABSOLUTE 0x00
396#define ARRAY_INDEX_RELATIVE 0x01
397
398/* matrix name */
399#define MATRIX_MODELVIEW 0x01
400#define MATRIX_PROJECTION 0x02
401#define MATRIX_MVP 0x03
402#define MATRIX_TEXTURE 0x04
403#define MATRIX_PALETTE 0x05
404#define MATRIX_PROGRAM 0x06
405
406/* matrix modifier */
407#define MATRIX_MODIFIER_IDENTITY 0x00
408#define MATRIX_MODIFIER_INVERSE 0x01
409#define MATRIX_MODIFIER_TRANSPOSE 0x02
410#define MATRIX_MODIFIER_INVTRANS 0x03
411
412/* constant type */
413#define CONSTANT_SCALAR 0x01
414#define CONSTANT_VECTOR 0x02
415
416/* program param type */
417#define PROGRAM_PARAM_ENV 0x01
418#define PROGRAM_PARAM_LOCAL 0x02
419
420/* register type */
421#define REGISTER_ATTRIB 0x01
422#define REGISTER_PARAM 0x02
423#define REGISTER_RESULT 0x03
424#define REGISTER_ESTABLISHED_NAME 0x04
425
426/* param binding */
427#define PARAM_NULL 0x00
428#define PARAM_ARRAY_ELEMENT 0x01
429#define PARAM_STATE_ELEMENT 0x02
430#define PARAM_PROGRAM_ELEMENT 0x03
431#define PARAM_PROGRAM_ELEMENTS 0x04
432#define PARAM_CONSTANT 0x05
433
434/* param state property */
435#define STATE_MATERIAL_PARSER 0x01
436#define STATE_LIGHT_PARSER 0x02
437#define STATE_LIGHT_MODEL 0x03
438#define STATE_LIGHT_PROD 0x04
439#define STATE_FOG 0x05
440#define STATE_MATRIX_ROWS 0x06
441/* GL_ARB_fragment_program */
442#define STATE_TEX_ENV 0x07
443#define STATE_DEPTH 0x08
444/* GL_ARB_vertex_program */
445#define STATE_TEX_GEN 0x09
446#define STATE_CLIP_PLANE 0x0A
447#define STATE_POINT 0x0B
448
449/* state material property */
450#define MATERIAL_AMBIENT 0x01
451#define MATERIAL_DIFFUSE 0x02
452#define MATERIAL_SPECULAR 0x03
453#define MATERIAL_EMISSION 0x04
454#define MATERIAL_SHININESS 0x05
455
456/* state light property */
457#define LIGHT_AMBIENT 0x01
458#define LIGHT_DIFFUSE 0x02
459#define LIGHT_SPECULAR 0x03
460#define LIGHT_POSITION 0x04
461#define LIGHT_ATTENUATION 0x05
462#define LIGHT_HALF 0x06
463#define LIGHT_SPOT_DIRECTION 0x07
464
465/* state light model property */
466#define LIGHT_MODEL_AMBIENT 0x01
467#define LIGHT_MODEL_SCENECOLOR 0x02
468
469/* state light product property */
470#define LIGHT_PROD_AMBIENT 0x01
471#define LIGHT_PROD_DIFFUSE 0x02
472#define LIGHT_PROD_SPECULAR 0x03
473
474/* state texture environment property */
475#define TEX_ENV_COLOR 0x01
476
477/* state texture generation coord property */
478#define TEX_GEN_EYE 0x01
479#define TEX_GEN_OBJECT 0x02
480
481/* state fog property */
482#define FOG_COLOR 0x01
483#define FOG_PARAMS 0x02
484
485/* state depth property */
486#define DEPTH_RANGE 0x01
487
488/* state point parameters property */
489#define POINT_SIZE 0x01
490#define POINT_ATTENUATION 0x02
491
492/* declaration */
493#define ATTRIB 0x01
494#define PARAM 0x02
495#define TEMP 0x03
496#define OUTPUT 0x04
497#define ALIAS 0x05
498/* GL_ARB_vertex_program */
499#define ADDRESS 0x06
500
501/*-----------------------------------------------------------------------
502 * From here on down is the semantic checking portion
503 *
504 */
505
506/**
507 * Variable Table Handling functions
508 */
509typedef enum
510{
511 vt_none,
512 vt_address,
513 vt_attrib,
514 vt_param,
515 vt_temp,
516 vt_output,
517 vt_alias
518} var_type;
519
520
Brian Paul7aebaf32005-10-30 21:23:23 +0000521/**
522 * Setting an explicit field for each of the binding properties is a bit
523 * wasteful of space, but it should be much more clear when reading later on..
Jouk Jansen40322e12004-04-05 08:50:36 +0000524 */
525struct var_cache
526{
Brian Paul6a769d92006-04-28 15:42:15 +0000527 const GLubyte *name; /* don't free() - no need */
Jouk Jansen40322e12004-04-05 08:50:36 +0000528 var_type type;
529 GLuint address_binding; /* The index of the address register we should
530 * be using */
531 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
Jouk Jansen40322e12004-04-05 08:50:36 +0000532 GLuint attrib_is_generic; /* If the attrib was specified through a generic
533 * vertex attrib */
534 GLuint temp_binding; /* The index of the temp register we are to use */
Brian Paul7aebaf32005-10-30 21:23:23 +0000535 GLuint output_binding; /* Output/result register number */
Jouk Jansen40322e12004-04-05 08:50:36 +0000536 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
537 * that this is aliased to */
538 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
539 * PROGRAM_ENV_PARAM} */
540 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
541 * the tokens representing our bound state (or constants)
542 * start */
543 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
544 * we take up with our state tokens or constants. Note that
545 * this is _not_ the same as the number of param registers
546 * we eventually use */
547 struct var_cache *next;
548};
549
550static GLvoid
551var_cache_create (struct var_cache **va)
552{
553 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
554 if (*va) {
555 (**va).name = NULL;
556 (**va).type = vt_none;
557 (**va).attrib_binding = ~0;
558 (**va).attrib_is_generic = 0;
559 (**va).temp_binding = ~0;
560 (**va).output_binding = ~0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000561 (**va).param_binding_type = ~0;
562 (**va).param_binding_begin = ~0;
563 (**va).param_binding_length = ~0;
564 (**va).alias_binding = NULL;
565 (**va).next = NULL;
566 }
567}
568
569static GLvoid
570var_cache_destroy (struct var_cache **va)
571{
572 if (*va) {
573 var_cache_destroy (&(**va).next);
574 _mesa_free (*va);
575 *va = NULL;
576 }
577}
578
579static GLvoid
580var_cache_append (struct var_cache **va, struct var_cache *nv)
581{
582 if (*va)
583 var_cache_append (&(**va).next, nv);
584 else
585 *va = nv;
586}
587
588static struct var_cache *
Brian Paula088f162006-09-05 23:08:51 +0000589var_cache_find (struct var_cache *va, const GLubyte * name)
Jouk Jansen40322e12004-04-05 08:50:36 +0000590{
Brian Paul0a360cf2005-01-17 01:21:03 +0000591 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000592
593 while (va) {
Brian Paulaa206952005-09-16 18:14:24 +0000594 if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000595 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000596 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000597 return va;
598 }
599
600 va = va->next;
601 }
602
603 return NULL;
604}
605
Brian Paula088f162006-09-05 23:08:51 +0000606
607
608/**
609 * Called when an error is detected while parsing/compiling a program.
610 * Sets the ctx->Program.ErrorString field to descript and records a
611 * GL_INVALID_OPERATION error.
612 * \param position position of error in program string
613 * \param descrip verbose error description
614 */
615static void
616program_error(GLcontext *ctx, GLint position, const char *descrip)
617{
618 if (descrip) {
619 const char *prefix = "glProgramString(", *suffix = ")";
620 char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
621 _mesa_strlen(prefix) +
622 _mesa_strlen(suffix) + 1);
623 if (str) {
624 _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix);
625 _mesa_error(ctx, GL_INVALID_OPERATION, str);
626 _mesa_free(str);
627 }
628 }
629 _mesa_set_program_error(ctx, position, descrip);
630}
631
632
633
Jouk Jansen40322e12004-04-05 08:50:36 +0000634/**
635 * constructs an integer from 4 GLubytes in LE format
636 */
637static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000638parse_position (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000639{
640 GLuint value;
641
642 value = (GLuint) (*(*inst)++);
643 value += (GLuint) (*(*inst)++) * 0x100;
644 value += (GLuint) (*(*inst)++) * 0x10000;
645 value += (GLuint) (*(*inst)++) * 0x1000000;
646
647 return value;
648}
649
650/**
651 * This will, given a string, lookup the string as a variable name in the
652 * var cache. If the name is found, the var cache node corresponding to the
653 * var name is returned. If it is not found, a new entry is allocated
654 *
655 * \param I Points into the binary array where the string identifier begins
656 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
657 * \return The location on the var_cache corresponding the the string starting at I
658 */
659static struct var_cache *
Brian Paula088f162006-09-05 23:08:51 +0000660parse_string (const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +0000661 struct arb_program *Program, GLuint * found)
662{
Brian Paula088f162006-09-05 23:08:51 +0000663 const GLubyte *i = *inst;
Jouk Jansen40322e12004-04-05 08:50:36 +0000664 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000665 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000666
667 *inst += _mesa_strlen ((char *) i) + 1;
668
669 va = var_cache_find (*vc_head, i);
670
671 if (va) {
672 *found = 1;
673 return va;
674 }
675
676 *found = 0;
677 var_cache_create (&va);
Brian Paul6a769d92006-04-28 15:42:15 +0000678 va->name = (const GLubyte *) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000679
680 var_cache_append (vc_head, va);
681
682 return va;
683}
684
685static char *
Brian Paula088f162006-09-05 23:08:51 +0000686parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000687{
Brian Paula088f162006-09-05 23:08:51 +0000688 const GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000689 (void) Program;
690
Jouk Jansen40322e12004-04-05 08:50:36 +0000691 *inst += _mesa_strlen ((char *) i) + 1;
692
693 return (char *) i;
694}
695
696/**
Brian Paul05908952004-06-08 15:20:23 +0000697 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000698 */
Brian Paul05908952004-06-08 15:20:23 +0000699static GLint
Brian Paula088f162006-09-05 23:08:51 +0000700parse_sign (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000701{
702 /*return *(*inst)++ != '+'; */
703
704 if (**inst == '-') {
705 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000706 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000707 }
708 else if (**inst == '+') {
709 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000710 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000711 }
712
Brian Paul05908952004-06-08 15:20:23 +0000713 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000714}
715
716/**
717 * parses and returns signed integer
718 */
719static GLint
Brian Paula088f162006-09-05 23:08:51 +0000720parse_integer (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000721{
722 GLint sign;
723 GLint value;
724
725 /* check if *inst points to '+' or '-'
726 * if yes, grab the sign and increment *inst
727 */
728 sign = parse_sign (inst);
729
730 /* now check if *inst points to 0
731 * if yes, increment the *inst and return the default value
732 */
733 if (**inst == 0) {
734 (*inst)++;
735 return 0;
736 }
737
738 /* parse the integer as you normally would do it */
739 value = _mesa_atoi (parse_string_without_adding (inst, Program));
740
741 /* now, after terminating 0 there is a position
742 * to parse it - parse_position()
743 */
744 Program->Position = parse_position (inst);
745
Brian Paul05908952004-06-08 15:20:23 +0000746 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000747}
748
749/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000750 Accumulate this string of digits, and return them as
751 a large integer represented in floating point (for range).
752 If scale is not NULL, also accumulates a power-of-ten
753 integer scale factor that represents the number of digits
754 in the string.
755*/
756static GLdouble
Brian Paula088f162006-09-05 23:08:51 +0000757parse_float_string(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
Brian Paul1ff8f502005-02-16 15:08:29 +0000758{
759 GLdouble value = 0.0;
760 GLdouble oscale = 1.0;
761
762 if (**inst == 0) { /* this string of digits is empty-- do nothing */
763 (*inst)++;
764 }
765 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000766 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000767 GLubyte digit = *((*inst)++);
768 value = value * 10.0 + (GLint) (digit - '0');
769 oscale *= 10.0;
770 }
771 assert(**inst == 0); /* integer string should end with 0 */
772 (*inst)++; /* skip over terminating 0 */
773 Program->Position = parse_position(inst); /* skip position (from integer) */
774 }
775 if (scale)
776 *scale = oscale;
777 return value;
778}
779
780/**
781 Parse an unsigned floating-point number from this stream of tokenized
782 characters. Example floating-point formats supported:
783 12.34
784 12
785 0.34
786 .34
787 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000788 */
789static GLfloat
Brian Paula088f162006-09-05 23:08:51 +0000790parse_float (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000791{
Brian Paul1ff8f502005-02-16 15:08:29 +0000792 GLint exponent;
793 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000794
Brian Paul1ff8f502005-02-16 15:08:29 +0000795 whole = parse_float_string(inst, Program, 0);
796 fraction = parse_float_string(inst, Program, &fracScale);
797
798 /* Parse signed exponent */
799 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000800
Brian Paul1ff8f502005-02-16 15:08:29 +0000801 /* Assemble parts of floating-point number: */
802 return (GLfloat) ((whole + fraction / fracScale) *
803 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000804}
805
806
807/**
808 */
809static GLfloat
Brian Paula088f162006-09-05 23:08:51 +0000810parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000811{
Brian Paul05908952004-06-08 15:20:23 +0000812 GLint sign = parse_sign (inst);
813 GLfloat value = parse_float (inst, Program);
814 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000815}
816
817/**
818 * This picks out a constant value from the parsed array. The constant vector is r
819 * returned in the *values array, which should be of length 4.
820 *
821 * \param values - The 4 component vector with the constant value in it
822 */
823static GLvoid
Brian Paula088f162006-09-05 23:08:51 +0000824parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000825 GLboolean use)
826{
827 GLuint components, i;
828
829
830 switch (*(*inst)++) {
831 case CONSTANT_SCALAR:
832 if (use == GL_TRUE) {
833 values[0] =
834 values[1] =
835 values[2] = values[3] = parse_float (inst, Program);
836 }
837 else {
838 values[0] =
839 values[1] =
840 values[2] = values[3] = parse_signed_float (inst, Program);
841 }
842
843 break;
844 case CONSTANT_VECTOR:
845 values[0] = values[1] = values[2] = 0;
846 values[3] = 1;
847 components = *(*inst)++;
848 for (i = 0; i < components; i++) {
849 values[i] = parse_signed_float (inst, Program);
850 }
851 break;
852 }
853}
854
855/**
856 * \param offset The offset from the address register that we should
857 * address
858 *
859 * \return 0 on sucess, 1 on error
860 */
861static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000862parse_relative_offset(GLcontext *ctx, const GLubyte **inst,
863 struct arb_program *Program, GLint *offset)
Jouk Jansen40322e12004-04-05 08:50:36 +0000864{
Brian Paul6a769d92006-04-28 15:42:15 +0000865 (void) ctx;
Jouk Jansen40322e12004-04-05 08:50:36 +0000866 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000867 return 0;
868}
869
870/**
871 * \param color 0 if color type is primary, 1 if color type is secondary
872 * \return 0 on sucess, 1 on error
873 */
874static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000875parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000876 GLint * color)
877{
Brian Paula6c423d2004-08-25 15:59:48 +0000878 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000879 *color = *(*inst)++ != COLOR_PRIMARY;
880 return 0;
881}
882
883/**
884 * Get an integer corresponding to a generic vertex attribute.
885 *
886 * \return 0 on sucess, 1 on error
887 */
888static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000889parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000890 struct arb_program *Program, GLuint *attrib)
891{
Brian Paulbd997cd2004-07-20 21:12:56 +0000892 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000893
Michal Krolbb38cad2006-04-11 11:41:11 +0000894 if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000895 {
Brian Paula088f162006-09-05 23:08:51 +0000896 program_error(ctx, Program->Position,
897 "Invalid generic vertex attribute index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000898 return 1;
899 }
900
Brian Paulbd997cd2004-07-20 21:12:56 +0000901 *attrib = (GLuint) i;
902
Jouk Jansen40322e12004-04-05 08:50:36 +0000903 return 0;
904}
905
906
907/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000908 * \param color The index of the color buffer to write into
909 * \return 0 on sucess, 1 on error
910 */
911static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000912parse_output_color_num (GLcontext * ctx, const GLubyte ** inst,
Brian Paulbe76b7f2004-10-04 14:40:05 +0000913 struct arb_program *Program, GLuint * color)
914{
915 GLint i = parse_integer (inst, Program);
916
917 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
Brian Paula088f162006-09-05 23:08:51 +0000918 program_error(ctx, Program->Position, "Invalid draw buffer index");
Brian Paulbe76b7f2004-10-04 14:40:05 +0000919 return 1;
920 }
921
922 *color = (GLuint) i;
923 return 0;
924}
925
926
927/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000928 * \param coord The texture unit index
929 * \return 0 on sucess, 1 on error
930 */
931static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000932parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000933 struct arb_program *Program, GLuint * coord)
934{
Brian Paulbd997cd2004-07-20 21:12:56 +0000935 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000936
Brian Paula6c423d2004-08-25 15:59:48 +0000937 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Brian Paula088f162006-09-05 23:08:51 +0000938 program_error(ctx, Program->Position, "Invalid texture unit index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000939 return 1;
940 }
941
Brian Paulbd997cd2004-07-20 21:12:56 +0000942 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000943 return 0;
944}
945
946/**
947 * \param coord The weight index
948 * \return 0 on sucess, 1 on error
949 */
950static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000951parse_weight_num (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000952 GLint * coord)
953{
954 *coord = parse_integer (inst, Program);
955
956 if ((*coord < 0) || (*coord >= 1)) {
Brian Paula088f162006-09-05 23:08:51 +0000957 program_error(ctx, Program->Position, "Invalid weight index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000958 return 1;
959 }
960
961 return 0;
962}
963
964/**
965 * \param coord The clip plane index
966 * \return 0 on sucess, 1 on error
967 */
968static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000969parse_clipplane_num (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000970 struct arb_program *Program, GLint * coord)
971{
972 *coord = parse_integer (inst, Program);
973
974 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
Brian Paula088f162006-09-05 23:08:51 +0000975 program_error(ctx, Program->Position, "Invalid clip plane index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000976 return 1;
977 }
978
979 return 0;
980}
981
982
983/**
984 * \return 0 on front face, 1 on back face
985 */
986static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000987parse_face_type (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000988{
989 switch (*(*inst)++) {
990 case FACE_FRONT:
991 return 0;
992
993 case FACE_BACK:
994 return 1;
995 }
996 return 0;
997}
998
999
1000/**
1001 * Given a matrix and a modifier token on the binary array, return tokens
1002 * that _mesa_fetch_state() [program.c] can understand.
1003 *
1004 * \param matrix - the matrix we are talking about
1005 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
1006 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
1007 * \return 0 on sucess, 1 on failure
1008 */
1009static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001010parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +00001011 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
1012{
1013 GLubyte mat = *(*inst)++;
1014
1015 *matrix_idx = 0;
1016
1017 switch (mat) {
1018 case MATRIX_MODELVIEW:
Brian65319522007-02-21 11:08:21 -07001019 *matrix = STATE_MODELVIEW_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001020 *matrix_idx = parse_integer (inst, Program);
1021 if (*matrix_idx > 0) {
Brian Paula088f162006-09-05 23:08:51 +00001022 program_error(ctx, Program->Position,
1023 "ARB_vertex_blend not supported");
Jouk Jansen40322e12004-04-05 08:50:36 +00001024 return 1;
1025 }
1026 break;
1027
1028 case MATRIX_PROJECTION:
Brian65319522007-02-21 11:08:21 -07001029 *matrix = STATE_PROJECTION_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001030 break;
1031
1032 case MATRIX_MVP:
Brian65319522007-02-21 11:08:21 -07001033 *matrix = STATE_MVP_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001034 break;
1035
1036 case MATRIX_TEXTURE:
Brian65319522007-02-21 11:08:21 -07001037 *matrix = STATE_TEXTURE_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001038 *matrix_idx = parse_integer (inst, Program);
1039 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
Brian Paula088f162006-09-05 23:08:51 +00001040 program_error(ctx, Program->Position, "Invalid Texture Unit");
1041 /* bad *matrix_id */
Jouk Jansen40322e12004-04-05 08:50:36 +00001042 return 1;
1043 }
1044 break;
1045
1046 /* This is not currently supported (ARB_matrix_palette) */
1047 case MATRIX_PALETTE:
1048 *matrix_idx = parse_integer (inst, Program);
Brian Paula088f162006-09-05 23:08:51 +00001049 program_error(ctx, Program->Position,
1050 "ARB_matrix_palette not supported");
Jouk Jansen40322e12004-04-05 08:50:36 +00001051 return 1;
1052 break;
1053
1054 case MATRIX_PROGRAM:
Brian65319522007-02-21 11:08:21 -07001055 *matrix = STATE_PROGRAM_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001056 *matrix_idx = parse_integer (inst, Program);
1057 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
Brian Paula088f162006-09-05 23:08:51 +00001058 program_error(ctx, Program->Position, "Invalid Program Matrix");
1059 /* bad *matrix_idx */
Jouk Jansen40322e12004-04-05 08:50:36 +00001060 return 1;
1061 }
1062 break;
1063 }
1064
1065 switch (*(*inst)++) {
1066 case MATRIX_MODIFIER_IDENTITY:
1067 *matrix_modifier = 0;
1068 break;
1069 case MATRIX_MODIFIER_INVERSE:
1070 *matrix_modifier = STATE_MATRIX_INVERSE;
1071 break;
1072 case MATRIX_MODIFIER_TRANSPOSE:
1073 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1074 break;
1075 case MATRIX_MODIFIER_INVTRANS:
1076 *matrix_modifier = STATE_MATRIX_INVTRANS;
1077 break;
1078 }
1079
1080 return 0;
1081}
1082
1083
1084/**
1085 * This parses a state string (rather, the binary version of it) into
1086 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1087 *
1088 * \param inst - the start in the binary arry to start working from
1089 * \param state_tokens - the storage for the 6-token state description
1090 * \return - 0 on sucess, 1 on error
1091 */
1092static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001093parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
Brianaa9d22a2007-02-23 11:21:03 -07001094 struct arb_program *Program,
1095 gl_state_index state_tokens[STATE_LENGTH])
Jouk Jansen40322e12004-04-05 08:50:36 +00001096{
1097 switch (*(*inst)++) {
1098 case STATE_MATERIAL_PARSER:
1099 state_tokens[0] = STATE_MATERIAL;
1100 state_tokens[1] = parse_face_type (inst);
1101 switch (*(*inst)++) {
1102 case MATERIAL_AMBIENT:
1103 state_tokens[2] = STATE_AMBIENT;
1104 break;
1105 case MATERIAL_DIFFUSE:
1106 state_tokens[2] = STATE_DIFFUSE;
1107 break;
1108 case MATERIAL_SPECULAR:
1109 state_tokens[2] = STATE_SPECULAR;
1110 break;
1111 case MATERIAL_EMISSION:
1112 state_tokens[2] = STATE_EMISSION;
1113 break;
1114 case MATERIAL_SHININESS:
1115 state_tokens[2] = STATE_SHININESS;
1116 break;
1117 }
1118 break;
1119
1120 case STATE_LIGHT_PARSER:
1121 state_tokens[0] = STATE_LIGHT;
1122 state_tokens[1] = parse_integer (inst, Program);
1123
1124 /* Check the value of state_tokens[1] against the # of lights */
1125 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
Brian Paula088f162006-09-05 23:08:51 +00001126 program_error(ctx, Program->Position, "Invalid Light Number");
1127 /* bad state_tokens[1] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001128 return 1;
1129 }
1130
1131 switch (*(*inst)++) {
1132 case LIGHT_AMBIENT:
1133 state_tokens[2] = STATE_AMBIENT;
1134 break;
1135 case LIGHT_DIFFUSE:
1136 state_tokens[2] = STATE_DIFFUSE;
1137 break;
1138 case LIGHT_SPECULAR:
1139 state_tokens[2] = STATE_SPECULAR;
1140 break;
1141 case LIGHT_POSITION:
1142 state_tokens[2] = STATE_POSITION;
1143 break;
1144 case LIGHT_ATTENUATION:
1145 state_tokens[2] = STATE_ATTENUATION;
1146 break;
1147 case LIGHT_HALF:
Brianf958aab2007-02-21 15:23:11 -07001148 state_tokens[2] = STATE_HALF_VECTOR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001149 break;
1150 case LIGHT_SPOT_DIRECTION:
1151 state_tokens[2] = STATE_SPOT_DIRECTION;
1152 break;
1153 }
1154 break;
1155
1156 case STATE_LIGHT_MODEL:
1157 switch (*(*inst)++) {
1158 case LIGHT_MODEL_AMBIENT:
1159 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1160 break;
1161 case LIGHT_MODEL_SCENECOLOR:
1162 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1163 state_tokens[1] = parse_face_type (inst);
1164 break;
1165 }
1166 break;
1167
1168 case STATE_LIGHT_PROD:
1169 state_tokens[0] = STATE_LIGHTPROD;
1170 state_tokens[1] = parse_integer (inst, Program);
1171
1172 /* Check the value of state_tokens[1] against the # of lights */
1173 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
Brian Paula088f162006-09-05 23:08:51 +00001174 program_error(ctx, Program->Position, "Invalid Light Number");
1175 /* bad state_tokens[1] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001176 return 1;
1177 }
1178
1179 state_tokens[2] = parse_face_type (inst);
1180 switch (*(*inst)++) {
1181 case LIGHT_PROD_AMBIENT:
1182 state_tokens[3] = STATE_AMBIENT;
1183 break;
1184 case LIGHT_PROD_DIFFUSE:
1185 state_tokens[3] = STATE_DIFFUSE;
1186 break;
1187 case LIGHT_PROD_SPECULAR:
1188 state_tokens[3] = STATE_SPECULAR;
1189 break;
1190 }
1191 break;
1192
1193
1194 case STATE_FOG:
1195 switch (*(*inst)++) {
1196 case FOG_COLOR:
Brianf1390a32007-02-23 17:11:01 -07001197 state_tokens[0] = STATE_FOG_COLOR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001198 break;
1199 case FOG_PARAMS:
Brianf1390a32007-02-23 17:11:01 -07001200 state_tokens[0] = STATE_FOG_PARAMS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001201 break;
1202 }
1203 break;
1204
1205 case STATE_TEX_ENV:
1206 state_tokens[1] = parse_integer (inst, Program);
1207 switch (*(*inst)++) {
1208 case TEX_ENV_COLOR:
1209 state_tokens[0] = STATE_TEXENV_COLOR;
1210 break;
1211 }
1212 break;
1213
1214 case STATE_TEX_GEN:
1215 {
1216 GLuint type, coord;
1217
1218 state_tokens[0] = STATE_TEXGEN;
1219 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1220
1221 if (parse_texcoord_num (ctx, inst, Program, &coord))
1222 return 1;
1223 state_tokens[1] = coord;
1224
1225 /* EYE or OBJECT */
1226 type = *(*inst++);
1227
1228 /* 0 - s, 1 - t, 2 - r, 3 - q */
1229 coord = *(*inst++);
1230
1231 if (type == TEX_GEN_EYE) {
1232 switch (coord) {
1233 case COMPONENT_X:
1234 state_tokens[2] = STATE_TEXGEN_EYE_S;
1235 break;
1236 case COMPONENT_Y:
1237 state_tokens[2] = STATE_TEXGEN_EYE_T;
1238 break;
1239 case COMPONENT_Z:
1240 state_tokens[2] = STATE_TEXGEN_EYE_R;
1241 break;
1242 case COMPONENT_W:
1243 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1244 break;
1245 }
1246 }
1247 else {
1248 switch (coord) {
1249 case COMPONENT_X:
1250 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1251 break;
1252 case COMPONENT_Y:
1253 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1254 break;
1255 case COMPONENT_Z:
1256 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1257 break;
1258 case COMPONENT_W:
1259 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1260 break;
1261 }
1262 }
1263 }
1264 break;
1265
1266 case STATE_DEPTH:
1267 switch (*(*inst)++) {
1268 case DEPTH_RANGE:
1269 state_tokens[0] = STATE_DEPTH_RANGE;
1270 break;
1271 }
1272 break;
1273
1274 case STATE_CLIP_PLANE:
1275 state_tokens[0] = STATE_CLIPPLANE;
1276 state_tokens[1] = parse_integer (inst, Program);
Brianaa9d22a2007-02-23 11:21:03 -07001277 if (parse_clipplane_num (ctx, inst, Program,
1278 (GLint *) &state_tokens[1]))
Jouk Jansen40322e12004-04-05 08:50:36 +00001279 return 1;
1280 break;
1281
1282 case STATE_POINT:
1283 switch (*(*inst++)) {
1284 case POINT_SIZE:
Brian776bc9c2007-02-22 09:29:46 -07001285 state_tokens[0] = STATE_POINT_SIZE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001286 break;
1287
1288 case POINT_ATTENUATION:
Brian776bc9c2007-02-22 09:29:46 -07001289 state_tokens[0] = STATE_POINT_ATTENUATION;
Jouk Jansen40322e12004-04-05 08:50:36 +00001290 break;
1291 }
1292 break;
1293
1294 /* XXX: I think this is the correct format for a matrix row */
1295 case STATE_MATRIX_ROWS:
Brianaa9d22a2007-02-23 11:21:03 -07001296 if (parse_matrix(ctx, inst, Program,
1297 (GLint *) &state_tokens[0],
1298 (GLint *) &state_tokens[1],
1299 (GLint *) &state_tokens[4]))
Jouk Jansen40322e12004-04-05 08:50:36 +00001300 return 1;
1301
Brian65319522007-02-21 11:08:21 -07001302 state_tokens[2] = parse_integer (inst, Program); /* The first row to grab */
Jouk Jansen40322e12004-04-05 08:50:36 +00001303
1304 if ((**inst) != 0) { /* Either the last row, 0 */
Brian65319522007-02-21 11:08:21 -07001305 state_tokens[3] = parse_integer (inst, Program);
1306 if (state_tokens[3] < state_tokens[2]) {
Brian Paula088f162006-09-05 23:08:51 +00001307 program_error(ctx, Program->Position,
1308 "Second matrix index less than the first");
1309 /* state_tokens[4] vs. state_tokens[3] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001310 return 1;
1311 }
1312 }
1313 else {
Brian65319522007-02-21 11:08:21 -07001314 state_tokens[3] = state_tokens[2];
Jouk Jansen40322e12004-04-05 08:50:36 +00001315 (*inst)++;
1316 }
1317 break;
1318 }
1319
1320 return 0;
1321}
1322
1323/**
1324 * This parses a state string (rather, the binary version of it) into
1325 * a 6-token similar for the state fetching code in program.c
1326 *
1327 * One might ask, why fetch these parameters into just like you fetch
1328 * state when they are already stored in other places?
1329 *
1330 * Because of array offsets -> We can stick env/local parameters in the
1331 * middle of a parameter array and then index someplace into the array
1332 * when we execute.
1333 *
1334 * One optimization might be to only do this for the cases where the
1335 * env/local parameters end up inside of an array, and leave the
1336 * single parameters (or arrays of pure env/local pareameters) in their
1337 * respective register files.
1338 *
1339 * For ENV parameters, the format is:
1340 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1341 * state_tokens[1] = STATE_ENV
1342 * state_tokens[2] = the parameter index
1343 *
1344 * for LOCAL parameters, the format is:
1345 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1346 * state_tokens[1] = STATE_LOCAL
1347 * state_tokens[2] = the parameter index
1348 *
1349 * \param inst - the start in the binary arry to start working from
1350 * \param state_tokens - the storage for the 6-token state description
1351 * \return - 0 on sucess, 1 on failure
1352 */
1353static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001354parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
Brianaa9d22a2007-02-23 11:21:03 -07001355 struct arb_program *Program,
1356 gl_state_index state_tokens[STATE_LENGTH])
Jouk Jansen40322e12004-04-05 08:50:36 +00001357{
1358 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1359 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1360 else
1361 state_tokens[0] = STATE_VERTEX_PROGRAM;
1362
1363
1364 switch (*(*inst)++) {
1365 case PROGRAM_PARAM_ENV:
1366 state_tokens[1] = STATE_ENV;
1367 state_tokens[2] = parse_integer (inst, Program);
1368
1369 /* Check state_tokens[2] against the number of ENV parameters available */
1370 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001371 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001372 ||
1373 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001374 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001375 program_error(ctx, Program->Position,
1376 "Invalid Program Env Parameter");
1377 /* bad state_tokens[2] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001378 return 1;
1379 }
1380
1381 break;
1382
1383 case PROGRAM_PARAM_LOCAL:
1384 state_tokens[1] = STATE_LOCAL;
1385 state_tokens[2] = parse_integer (inst, Program);
1386
1387 /* Check state_tokens[2] against the number of LOCAL parameters available */
1388 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001389 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001390 ||
1391 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001392 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001393 program_error(ctx, Program->Position,
1394 "Invalid Program Local Parameter");
1395 /* bad state_tokens[2] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001396 return 1;
1397 }
1398 break;
1399 }
1400
1401 return 0;
1402}
1403
1404/**
1405 * For ARB_vertex_program, programs are not allowed to use both an explicit
1406 * vertex attribute and a generic vertex attribute corresponding to the same
1407 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1408 *
1409 * This will walk our var_cache and make sure that nobody does anything fishy.
1410 *
1411 * \return 0 on sucess, 1 on error
1412 */
1413static GLuint
1414generic_attrib_check(struct var_cache *vc_head)
1415{
1416 int a;
1417 struct var_cache *curr;
1418 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1419 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1420
1421 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1422 explicitAttrib[a] = GL_FALSE;
1423 genericAttrib[a] = GL_FALSE;
1424 }
1425
1426 curr = vc_head;
1427 while (curr) {
1428 if (curr->type == vt_attrib) {
1429 if (curr->attrib_is_generic)
Brian Paul18e7c5c2005-10-30 21:46:00 +00001430 genericAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001431 else
Brian Paul18e7c5c2005-10-30 21:46:00 +00001432 explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001433 }
1434
1435 curr = curr->next;
1436 }
1437
1438 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1439 if ((explicitAttrib[a]) && (genericAttrib[a]))
1440 return 1;
1441 }
1442
1443 return 0;
1444}
1445
1446/**
1447 * This will handle the binding side of an ATTRIB var declaration
1448 *
Brian Paul18e7c5c2005-10-30 21:46:00 +00001449 * \param inputReg returns the input register index, one of the
1450 * VERT_ATTRIB_* or FRAG_ATTRIB_* values.
Brian Paula088f162006-09-05 23:08:51 +00001451 * \return returns 0 on success, 1 on error
Jouk Jansen40322e12004-04-05 08:50:36 +00001452 */
1453static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001454parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
Brian Paul18e7c5c2005-10-30 21:46:00 +00001455 struct arb_program *Program,
1456 GLuint *inputReg, GLuint *is_generic)
Jouk Jansen40322e12004-04-05 08:50:36 +00001457{
Jouk Jansen40322e12004-04-05 08:50:36 +00001458 GLint err = 0;
1459
1460 *is_generic = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001461
Jouk Jansen40322e12004-04-05 08:50:36 +00001462 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1463 switch (*(*inst)++) {
1464 case FRAGMENT_ATTRIB_COLOR:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001465 {
1466 GLint coord;
1467 err = parse_color_type (ctx, inst, Program, &coord);
1468 *inputReg = FRAG_ATTRIB_COL0 + coord;
1469 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001470 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001471 case FRAGMENT_ATTRIB_TEXCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001472 {
Brian8fa6f732007-02-01 09:24:41 -07001473 GLuint texcoord = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001474 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1475 *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
1476 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001477 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001478 case FRAGMENT_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001479 *inputReg = FRAG_ATTRIB_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001480 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001481 case FRAGMENT_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001482 *inputReg = FRAG_ATTRIB_WPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001483 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001484 default:
1485 err = 1;
1486 break;
1487 }
1488 }
1489 else {
1490 switch (*(*inst)++) {
1491 case VERTEX_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001492 *inputReg = VERT_ATTRIB_POS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001493 break;
1494
1495 case VERTEX_ATTRIB_WEIGHT:
1496 {
1497 GLint weight;
Jouk Jansen40322e12004-04-05 08:50:36 +00001498 err = parse_weight_num (ctx, inst, Program, &weight);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001499 *inputReg = VERT_ATTRIB_WEIGHT;
Brian Paul3a557502006-09-05 23:15:29 +00001500#if 1
1501 /* hack for Warcraft (see bug 8060) */
1502 _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported.");
Brian Pauld9aebd82006-09-06 05:03:47 +00001503 break;
Brian Paul3a557502006-09-05 23:15:29 +00001504#else
Brian Paula088f162006-09-05 23:08:51 +00001505 program_error(ctx, Program->Position,
1506 "ARB_vertex_blend not supported");
Brian Pauld9aebd82006-09-06 05:03:47 +00001507 return 1;
Brian Paul3a557502006-09-05 23:15:29 +00001508#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00001509 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001510
1511 case VERTEX_ATTRIB_NORMAL:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001512 *inputReg = VERT_ATTRIB_NORMAL;
Jouk Jansen40322e12004-04-05 08:50:36 +00001513 break;
1514
1515 case VERTEX_ATTRIB_COLOR:
1516 {
1517 GLint color;
Jouk Jansen40322e12004-04-05 08:50:36 +00001518 err = parse_color_type (ctx, inst, Program, &color);
1519 if (color) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001520 *inputReg = VERT_ATTRIB_COLOR1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001521 }
1522 else {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001523 *inputReg = VERT_ATTRIB_COLOR0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001524 }
1525 }
1526 break;
1527
1528 case VERTEX_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001529 *inputReg = VERT_ATTRIB_FOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00001530 break;
1531
1532 case VERTEX_ATTRIB_TEXCOORD:
1533 {
Brian8fa6f732007-02-01 09:24:41 -07001534 GLuint unit = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001535 err = parse_texcoord_num (ctx, inst, Program, &unit);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001536 *inputReg = VERT_ATTRIB_TEX0 + unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001537 }
1538 break;
1539
Jouk Jansen40322e12004-04-05 08:50:36 +00001540 case VERTEX_ATTRIB_MATRIXINDEX:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001541 /* Not supported at this time */
1542 {
1543 const char *msg = "ARB_palette_matrix not supported";
1544 parse_integer (inst, Program);
Brian Paula088f162006-09-05 23:08:51 +00001545 program_error(ctx, Program->Position, msg);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001546 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001547 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001548
1549 case VERTEX_ATTRIB_GENERIC:
1550 {
1551 GLuint attrib;
Tilman Sauerbeck6c334752006-06-28 16:26:20 +00001552 err = parse_generic_attrib_num(ctx, inst, Program, &attrib);
Brian Paula088f162006-09-05 23:08:51 +00001553 if (!err) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001554 *is_generic = 1;
Brian Paul095c6692006-04-25 00:21:32 +00001555 /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's
1556 * attributes do not alias the conventional vertex
1557 * attributes.
1558 */
1559 if (attrib > 0)
1560 *inputReg = attrib + VERT_ATTRIB_GENERIC0;
Brian Paul919f6a02006-05-29 14:37:56 +00001561 else
1562 *inputReg = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001563 }
1564 }
1565 break;
1566
1567 default:
1568 err = 1;
1569 break;
1570 }
1571 }
1572
Jouk Jansen40322e12004-04-05 08:50:36 +00001573 if (err) {
Brian Paula088f162006-09-05 23:08:51 +00001574 program_error(ctx, Program->Position, "Bad attribute binding");
Jouk Jansen40322e12004-04-05 08:50:36 +00001575 }
1576
Brian Paulde997602005-11-12 17:53:14 +00001577 Program->Base.InputsRead |= (1 << *inputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001578
1579 return err;
1580}
1581
Brian Paul7aebaf32005-10-30 21:23:23 +00001582
Jouk Jansen40322e12004-04-05 08:50:36 +00001583/**
1584 * This translates between a binary token for an output variable type
1585 * and the mesa token for the same thing.
1586 *
Brian Paul7aebaf32005-10-30 21:23:23 +00001587 * \param inst The parsed tokens
1588 * \param outputReg Returned index/number of the output register,
Brian Paul90ebb582005-11-02 18:06:12 +00001589 * one of the VERT_RESULT_* or FRAG_RESULT_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001590 */
1591static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001592parse_result_binding(GLcontext *ctx, const GLubyte **inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00001593 GLuint *outputReg, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00001594{
Brian Paul7aebaf32005-10-30 21:23:23 +00001595 const GLubyte token = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001596
Brian Paul7aebaf32005-10-30 21:23:23 +00001597 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001598 case FRAGMENT_RESULT_COLOR:
Jouk Jansen40322e12004-04-05 08:50:36 +00001599 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001600 GLuint out_color;
1601
Brian Paulbe76b7f2004-10-04 14:40:05 +00001602 /* This gets result of the color buffer we're supposed to
Brian Paul7aebaf32005-10-30 21:23:23 +00001603 * draw into. This pertains to GL_ARB_draw_buffers.
Brian Paulbe76b7f2004-10-04 14:40:05 +00001604 */
1605 parse_output_color_num(ctx, inst, Program, &out_color);
Brian Paul7aebaf32005-10-30 21:23:23 +00001606 ASSERT(out_color < MAX_DRAW_BUFFERS);
Brian Paul90ebb582005-11-02 18:06:12 +00001607 *outputReg = FRAG_RESULT_COLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001608 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001609 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001610 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1611 *outputReg = VERT_RESULT_HPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001612 }
1613 break;
1614
1615 case FRAGMENT_RESULT_DEPTH:
Jouk Jansen40322e12004-04-05 08:50:36 +00001616 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001617 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
Brian Paul90ebb582005-11-02 18:06:12 +00001618 *outputReg = FRAG_RESULT_DEPR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001619 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001620 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001621 /* for vtx programs, this is VERTEX_RESULT_COLOR */
Jouk Jansen40322e12004-04-05 08:50:36 +00001622 GLint color_type;
1623 GLuint face_type = parse_face_type(inst);
Brian Paul7aebaf32005-10-30 21:23:23 +00001624 GLint err = parse_color_type(ctx, inst, Program, &color_type);
1625 if (err)
1626 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001627
Jouk Jansen40322e12004-04-05 08:50:36 +00001628 if (face_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001629 /* back face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001630 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001631 *outputReg = VERT_RESULT_BFC1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001632 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001633 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001634 *outputReg = VERT_RESULT_BFC0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001635 }
1636 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001637 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001638 /* front face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001639 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001640 *outputReg = VERT_RESULT_COL1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001641 }
1642 /* primary color */
1643 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001644 *outputReg = VERT_RESULT_COL0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001645 }
1646 }
1647 }
1648 break;
1649
1650 case VERTEX_RESULT_FOGCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001651 *outputReg = VERT_RESULT_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001652 break;
1653
1654 case VERTEX_RESULT_POINTSIZE:
Brian Paul7aebaf32005-10-30 21:23:23 +00001655 *outputReg = VERT_RESULT_PSIZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00001656 break;
1657
1658 case VERTEX_RESULT_TEXCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001659 {
1660 GLuint unit;
1661 if (parse_texcoord_num (ctx, inst, Program, &unit))
1662 return 1;
1663 *outputReg = VERT_RESULT_TEX0 + unit;
1664 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001665 break;
1666 }
1667
Brian Paulde997602005-11-12 17:53:14 +00001668 Program->Base.OutputsWritten |= (1 << *outputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001669
1670 return 0;
1671}
1672
Brian Paul7aebaf32005-10-30 21:23:23 +00001673
Jouk Jansen40322e12004-04-05 08:50:36 +00001674/**
1675 * This handles the declaration of ATTRIB variables
1676 *
1677 * XXX: Still needs
1678 * parse_vert_attrib_binding(), or something like that
1679 *
1680 * \return 0 on sucess, 1 on error
1681 */
1682static GLint
Brian Paula088f162006-09-05 23:08:51 +00001683parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001684 struct arb_program *Program)
1685{
1686 GLuint found;
1687 char *error_msg;
1688 struct var_cache *attrib_var;
1689
1690 attrib_var = parse_string (inst, vc_head, Program, &found);
1691 Program->Position = parse_position (inst);
1692 if (found) {
1693 error_msg = (char *)
1694 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1695 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1696 attrib_var->name);
Brian Paula088f162006-09-05 23:08:51 +00001697 program_error(ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001698 _mesa_free (error_msg);
1699 return 1;
1700 }
1701
1702 attrib_var->type = vt_attrib;
1703
Brian Paul7aebaf32005-10-30 21:23:23 +00001704 if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
Brian Paul7aebaf32005-10-30 21:23:23 +00001705 &attrib_var->attrib_is_generic))
1706 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001707
Brian Paul7aebaf32005-10-30 21:23:23 +00001708 if (generic_attrib_check(*vc_head)) {
Brian Paula088f162006-09-05 23:08:51 +00001709 program_error(ctx, Program->Position,
1710 "Cannot use both a generic vertex attribute "
1711 "and a specific attribute of the same type");
Brian Paul7aebaf32005-10-30 21:23:23 +00001712 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001713 }
1714
1715 Program->Base.NumAttributes++;
1716 return 0;
1717}
1718
1719/**
1720 * \param use -- TRUE if we're called when declaring implicit parameters,
1721 * FALSE if we're declaraing variables. This has to do with
1722 * if we get a signed or unsigned float for scalar constants
1723 */
1724static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001725parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00001726 struct var_cache *param_var,
1727 struct arb_program *Program, GLboolean use)
1728{
1729 GLint idx;
Brian Paul7aebaf32005-10-30 21:23:23 +00001730 GLuint err = 0;
Brianaa9d22a2007-02-23 11:21:03 -07001731 gl_state_index state_tokens[STATE_LENGTH];
Jouk Jansen40322e12004-04-05 08:50:36 +00001732 GLfloat const_values[4];
1733
Jouk Jansen40322e12004-04-05 08:50:36 +00001734 switch (*(*inst)++) {
1735 case PARAM_STATE_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001736 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1737 return 1;
1738
1739 /* If we adding STATE_MATRIX that has multiple rows, we need to
1740 * unroll it and call _mesa_add_state_reference() for each row
1741 */
Brian65319522007-02-21 11:08:21 -07001742 if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
1743 state_tokens[0] == STATE_PROJECTION_MATRIX ||
1744 state_tokens[0] == STATE_MVP_MATRIX ||
1745 state_tokens[0] == STATE_TEXTURE_MATRIX ||
1746 state_tokens[0] == STATE_PROGRAM_MATRIX)
1747 && (state_tokens[2] != state_tokens[3])) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001748 GLint row;
Brian65319522007-02-21 11:08:21 -07001749 const GLint first_row = state_tokens[2];
1750 const GLint last_row = state_tokens[3];
Jouk Jansen40322e12004-04-05 08:50:36 +00001751
1752 for (row = first_row; row <= last_row; row++) {
Brian65319522007-02-21 11:08:21 -07001753 state_tokens[2] = state_tokens[3] = row;
Jouk Jansen40322e12004-04-05 08:50:36 +00001754
Brian Paulde997602005-11-12 17:53:14 +00001755 idx = _mesa_add_state_reference(Program->Base.Parameters,
1756 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001757 if (param_var->param_binding_begin == ~0U)
1758 param_var->param_binding_begin = idx;
1759 param_var->param_binding_length++;
1760 Program->Base.NumParameters++;
1761 }
1762 }
1763 else {
Brian Paulde997602005-11-12 17:53:14 +00001764 idx = _mesa_add_state_reference(Program->Base.Parameters,
1765 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001766 if (param_var->param_binding_begin == ~0U)
1767 param_var->param_binding_begin = idx;
1768 param_var->param_binding_length++;
1769 Program->Base.NumParameters++;
1770 }
1771 break;
1772
1773 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001774 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1775 return 1;
Brian Paulde997602005-11-12 17:53:14 +00001776 idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001777 if (param_var->param_binding_begin == ~0U)
1778 param_var->param_binding_begin = idx;
1779 param_var->param_binding_length++;
1780 Program->Base.NumParameters++;
1781
1782 /* Check if there is more: 0 -> we're done, else its an integer */
1783 if (**inst) {
1784 GLuint out_of_range, new_idx;
1785 GLuint start_idx = state_tokens[2] + 1;
1786 GLuint end_idx = parse_integer (inst, Program);
1787
1788 out_of_range = 0;
1789 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1790 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001791 && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001792 || ((state_tokens[1] == STATE_LOCAL)
1793 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001794 ctx->Const.FragmentProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001795 out_of_range = 1;
1796 }
1797 else {
1798 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001799 && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001800 || ((state_tokens[1] == STATE_LOCAL)
1801 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001802 ctx->Const.VertexProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001803 out_of_range = 1;
1804 }
1805 if (out_of_range) {
Brian Paula088f162006-09-05 23:08:51 +00001806 program_error(ctx, Program->Position,
1807 "Invalid Program Parameter"); /*end_idx*/
Jouk Jansen40322e12004-04-05 08:50:36 +00001808 return 1;
1809 }
1810
1811 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1812 state_tokens[2] = new_idx;
Brian Paulde997602005-11-12 17:53:14 +00001813 idx = _mesa_add_state_reference(Program->Base.Parameters,
1814 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001815 param_var->param_binding_length++;
1816 Program->Base.NumParameters++;
1817 }
1818 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001819 else {
1820 (*inst)++;
1821 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001822 break;
1823
1824 case PARAM_CONSTANT:
1825 parse_constant (inst, const_values, Program, use);
Brian Paulde997602005-11-12 17:53:14 +00001826 idx = _mesa_add_named_constant(Program->Base.Parameters,
1827 (char *) param_var->name,
Brian Paul0c6723a2006-11-15 23:38:02 +00001828 const_values, 4);
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 break;
1834
1835 default:
Brian Paula088f162006-09-05 23:08:51 +00001836 program_error(ctx, Program->Position,
1837 "Unexpected token (in parse_param_elements())");
Jouk Jansen40322e12004-04-05 08:50:36 +00001838 return 1;
1839 }
1840
1841 /* Make sure we haven't blown past our parameter limits */
1842 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1843 (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001844 ctx->Const.VertexProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001845 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1846 && (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001847 ctx->Const.FragmentProgram.MaxLocalParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001848 program_error(ctx, Program->Position, "Too many parameter variables");
Jouk Jansen40322e12004-04-05 08:50:36 +00001849 return 1;
1850 }
1851
1852 return err;
1853}
1854
Brian Paul7aebaf32005-10-30 21:23:23 +00001855
Jouk Jansen40322e12004-04-05 08:50:36 +00001856/**
1857 * This picks out PARAM program parameter bindings.
1858 *
1859 * XXX: This needs to be stressed & tested
1860 *
1861 * \return 0 on sucess, 1 on error
1862 */
1863static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001864parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001865 struct arb_program *Program)
1866{
Brian Paulbd997cd2004-07-20 21:12:56 +00001867 GLuint found, err;
1868 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001869 struct var_cache *param_var;
1870
1871 err = 0;
1872 param_var = parse_string (inst, vc_head, Program, &found);
1873 Program->Position = parse_position (inst);
1874
1875 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001876 char *error_msg = (char *)
1877 _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
Jouk Jansen40322e12004-04-05 08:50:36 +00001878 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1879 param_var->name);
Brian Paula088f162006-09-05 23:08:51 +00001880 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001881 _mesa_free (error_msg);
1882 return 1;
1883 }
1884
1885 specified_length = parse_integer (inst, Program);
1886
1887 if (specified_length < 0) {
Brian Paula088f162006-09-05 23:08:51 +00001888 program_error(ctx, Program->Position, "Negative parameter array length");
Jouk Jansen40322e12004-04-05 08:50:36 +00001889 return 1;
1890 }
1891
1892 param_var->type = vt_param;
1893 param_var->param_binding_length = 0;
1894
1895 /* Right now, everything is shoved into the main state register file.
1896 *
1897 * In the future, it would be nice to leave things ENV/LOCAL params
1898 * in their respective register files, if possible
1899 */
1900 param_var->param_binding_type = PROGRAM_STATE_VAR;
1901
1902 /* Remember to:
1903 * * - add each guy to the parameter list
1904 * * - increment the param_var->param_binding_len
1905 * * - store the param_var->param_binding_begin for the first one
1906 * * - compare the actual len to the specified len at the end
1907 */
1908 while (**inst != PARAM_NULL) {
1909 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1910 return 1;
1911 }
1912
1913 /* Test array length here! */
1914 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001915 if (specified_length != (int)param_var->param_binding_length) {
Brian Paula088f162006-09-05 23:08:51 +00001916 program_error(ctx, Program->Position,
1917 "Declared parameter array length does not match parameter list");
Jouk Jansen40322e12004-04-05 08:50:36 +00001918 }
1919 }
1920
1921 (*inst)++;
1922
1923 return 0;
1924}
1925
1926/**
1927 *
1928 */
1929static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001930parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001931 struct arb_program *Program, struct var_cache **new_var)
1932{
1933 struct var_cache *param_var;
1934
1935 /* First, insert a dummy entry into the var_cache */
1936 var_cache_create (&param_var);
Brian Paul6a769d92006-04-28 15:42:15 +00001937 param_var->name = (const GLubyte *) " ";
Jouk Jansen40322e12004-04-05 08:50:36 +00001938 param_var->type = vt_param;
1939
1940 param_var->param_binding_length = 0;
1941 /* Don't fill in binding_begin; We use the default value of -1
1942 * to tell if its already initialized, elsewhere.
1943 *
1944 * param_var->param_binding_begin = 0;
1945 */
1946 param_var->param_binding_type = PROGRAM_STATE_VAR;
1947
1948 var_cache_append (vc_head, param_var);
1949
1950 /* Then fill it with juicy parameter goodness */
1951 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1952 return 1;
1953
1954 *new_var = param_var;
1955
1956 return 0;
1957}
1958
1959
1960/**
1961 * This handles the declaration of TEMP variables
1962 *
1963 * \return 0 on sucess, 1 on error
1964 */
1965static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001966parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001967 struct arb_program *Program)
1968{
1969 GLuint found;
1970 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00001971
1972 while (**inst != 0) {
1973 temp_var = parse_string (inst, vc_head, Program, &found);
1974 Program->Position = parse_position (inst);
1975 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001976 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001977 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
1978 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1979 temp_var->name);
Brian Paula088f162006-09-05 23:08:51 +00001980 program_error(ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001981 _mesa_free (error_msg);
1982 return 1;
1983 }
1984
1985 temp_var->type = vt_temp;
1986
1987 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1988 (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001989 ctx->Const.FragmentProgram.MaxTemps))
Jouk Jansen40322e12004-04-05 08:50:36 +00001990 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
1991 && (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001992 ctx->Const.VertexProgram.MaxTemps))) {
Brian Paula088f162006-09-05 23:08:51 +00001993 program_error(ctx, Program->Position,
1994 "Too many TEMP variables declared");
Jouk Jansen40322e12004-04-05 08:50:36 +00001995 return 1;
1996 }
1997
1998 temp_var->temp_binding = Program->Base.NumTemporaries;
1999 Program->Base.NumTemporaries++;
2000 }
2001 (*inst)++;
2002
2003 return 0;
2004}
2005
2006/**
2007 * This handles variables of the OUTPUT variety
2008 *
2009 * \return 0 on sucess, 1 on error
2010 */
2011static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002012parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002013 struct arb_program *Program)
2014{
2015 GLuint found;
2016 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00002017 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002018
2019 output_var = parse_string (inst, vc_head, Program, &found);
2020 Program->Position = parse_position (inst);
2021 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002022 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002023 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
2024 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2025 output_var->name);
Brian Paula088f162006-09-05 23:08:51 +00002026 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002027 _mesa_free (error_msg);
2028 return 1;
2029 }
2030
2031 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002032
2033 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2034 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002035}
2036
2037/**
2038 * This handles variables of the ALIAS kind
2039 *
2040 * \return 0 on sucess, 1 on error
2041 */
2042static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002043parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002044 struct arb_program *Program)
2045{
2046 GLuint found;
2047 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002048
2049 temp_var = parse_string (inst, vc_head, Program, &found);
2050 Program->Position = parse_position (inst);
2051
2052 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002053 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002054 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2055 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2056 temp_var->name);
Brian Paula088f162006-09-05 23:08:51 +00002057 program_error(ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002058 _mesa_free (error_msg);
2059 return 1;
2060 }
2061
2062 temp_var->type = vt_alias;
2063 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2064 Program->Position = parse_position (inst);
2065
2066 if (!found)
2067 {
Brian Paul7aebaf32005-10-30 21:23:23 +00002068 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002069 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2070 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2071 temp_var->alias_binding->name);
Brian Paula088f162006-09-05 23:08:51 +00002072 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002073 _mesa_free (error_msg);
2074 return 1;
2075 }
2076
2077 return 0;
2078}
2079
2080/**
2081 * This handles variables of the ADDRESS kind
2082 *
2083 * \return 0 on sucess, 1 on error
2084 */
2085static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002086parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002087 struct arb_program *Program)
2088{
2089 GLuint found;
2090 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002091
2092 while (**inst != 0) {
2093 temp_var = parse_string (inst, vc_head, Program, &found);
2094 Program->Position = parse_position (inst);
2095 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002096 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002097 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2098 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2099 temp_var->name);
Brian Paula088f162006-09-05 23:08:51 +00002100 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002101 _mesa_free (error_msg);
2102 return 1;
2103 }
2104
2105 temp_var->type = vt_address;
2106
2107 if (Program->Base.NumAddressRegs >=
Brian Paul05051032005-11-01 04:36:33 +00002108 ctx->Const.VertexProgram.MaxAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002109 const char *msg = "Too many ADDRESS variables declared";
Brian Paula088f162006-09-05 23:08:51 +00002110 program_error(ctx, Program->Position, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002111 return 1;
2112 }
2113
2114 temp_var->address_binding = Program->Base.NumAddressRegs;
2115 Program->Base.NumAddressRegs++;
2116 }
2117 (*inst)++;
2118
2119 return 0;
2120}
2121
2122/**
2123 * Parse a program declaration
2124 *
2125 * \return 0 on sucess, 1 on error
2126 */
2127static GLint
Brian Paula088f162006-09-05 23:08:51 +00002128parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002129 struct arb_program *Program)
2130{
2131 GLint err = 0;
2132
2133 switch (*(*inst)++) {
2134 case ADDRESS:
2135 err = parse_address (ctx, inst, vc_head, Program);
2136 break;
2137
2138 case ALIAS:
2139 err = parse_alias (ctx, inst, vc_head, Program);
2140 break;
2141
2142 case ATTRIB:
2143 err = parse_attrib (ctx, inst, vc_head, Program);
2144 break;
2145
2146 case OUTPUT:
2147 err = parse_output (ctx, inst, vc_head, Program);
2148 break;
2149
2150 case PARAM:
2151 err = parse_param (ctx, inst, vc_head, Program);
2152 break;
2153
2154 case TEMP:
2155 err = parse_temp (ctx, inst, vc_head, Program);
2156 break;
2157 }
2158
2159 return err;
2160}
2161
2162/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002163 * Handle the parsing out of a masked destination register, either for a
2164 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002165 *
2166 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002167 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002168 * position invariant
2169 *
2170 * \param File - The register file we write to
2171 * \param Index - The register index we write to
2172 * \param WriteMask - The mask controlling which components we write (1->write)
2173 *
2174 * \return 0 on sucess, 1 on error
2175 */
2176static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002177parse_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002178 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002179 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002180{
Brian Paul7aebaf32005-10-30 21:23:23 +00002181 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002182 struct var_cache *dst;
2183
2184 /* We either have a result register specified, or a
2185 * variable that may or may not be writable
2186 */
2187 switch (*(*inst)++) {
2188 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002189 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002190 return 1;
2191 *File = PROGRAM_OUTPUT;
2192 break;
2193
2194 case REGISTER_ESTABLISHED_NAME:
2195 dst = parse_string (inst, vc_head, Program, &result);
2196 Program->Position = parse_position (inst);
2197
2198 /* If the name has never been added to our symbol table, we're hosed */
2199 if (!result) {
Brian Paula088f162006-09-05 23:08:51 +00002200 program_error(ctx, Program->Position, "0: Undefined variable");
Jouk Jansen40322e12004-04-05 08:50:36 +00002201 return 1;
2202 }
2203
2204 switch (dst->type) {
2205 case vt_output:
2206 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002207 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002208 break;
2209
2210 case vt_temp:
2211 *File = PROGRAM_TEMPORARY;
2212 *Index = dst->temp_binding;
2213 break;
2214
2215 /* If the var type is not vt_output or vt_temp, no go */
2216 default:
Brian Paula088f162006-09-05 23:08:51 +00002217 program_error(ctx, Program->Position,
2218 "Destination register is read only");
Jouk Jansen40322e12004-04-05 08:50:36 +00002219 return 1;
2220 }
2221 break;
2222
2223 default:
Brian Paula088f162006-09-05 23:08:51 +00002224 program_error(ctx, Program->Position,
2225 "Unexpected opcode in parse_masked_dst_reg()");
Jouk Jansen40322e12004-04-05 08:50:36 +00002226 return 1;
2227 }
2228
2229
2230 /* Position invariance test */
2231 /* This test is done now in syntax portion - when position invariance OPTION
2232 is specified, "result.position" rule is disabled so there is no way
2233 to write the position
2234 */
2235 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2236 (*Index == 0)) {
Brian Paula088f162006-09-05 23:08:51 +00002237 program_error(ctx, Program->Position,
Jouk Jansen40322e12004-04-05 08:50:36 +00002238 "Vertex program specified position invariance and wrote vertex position");
2239 }*/
2240
2241 /* And then the mask.
2242 * w,a -> bit 0
2243 * z,b -> bit 1
2244 * y,g -> bit 2
2245 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002246 *
2247 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002248 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002249 tmp = (GLint) *(*inst)++;
2250 *WriteMask = (((tmp>>3) & 0x1) |
2251 ((tmp>>1) & 0x2) |
2252 ((tmp<<1) & 0x4) |
2253 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002254
2255 return 0;
2256}
2257
2258
2259/**
2260 * Handle the parsing of a address register
2261 *
2262 * \param Index - The register index we write to
2263 *
2264 * \return 0 on sucess, 1 on error
2265 */
2266static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002267parse_address_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002268 struct var_cache **vc_head,
2269 struct arb_program *Program, GLint * Index)
2270{
2271 struct var_cache *dst;
2272 GLuint result;
Aapo Tahkola6fc864b2006-03-22 21:29:15 +00002273
2274 *Index = 0; /* XXX */
Jouk Jansen40322e12004-04-05 08:50:36 +00002275
2276 dst = parse_string (inst, vc_head, Program, &result);
2277 Program->Position = parse_position (inst);
2278
2279 /* If the name has never been added to our symbol table, we're hosed */
2280 if (!result) {
Brian Paula088f162006-09-05 23:08:51 +00002281 program_error(ctx, Program->Position, "Undefined variable");
Jouk Jansen40322e12004-04-05 08:50:36 +00002282 return 1;
2283 }
2284
2285 if (dst->type != vt_address) {
Brian Paula088f162006-09-05 23:08:51 +00002286 program_error(ctx, Program->Position, "Variable is not of type ADDRESS");
Jouk Jansen40322e12004-04-05 08:50:36 +00002287 return 1;
2288 }
2289
2290 return 0;
2291}
2292
Brian Paul8e8fa632005-07-01 02:03:33 +00002293#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002294/**
2295 * Handle the parsing out of a masked address register
2296 *
2297 * \param Index - The register index we write to
2298 * \param WriteMask - The mask controlling which components we write (1->write)
2299 *
2300 * \return 0 on sucess, 1 on error
2301 */
2302static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002303parse_masked_address_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002304 struct var_cache **vc_head,
2305 struct arb_program *Program, GLint * Index,
2306 GLboolean * WriteMask)
2307{
2308 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2309 return 1;
2310
2311 /* This should be 0x8 */
2312 (*inst)++;
2313
2314 /* Writemask of .x is implied */
2315 WriteMask[0] = 1;
2316 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2317
2318 return 0;
2319}
Brian Paul8e8fa632005-07-01 02:03:33 +00002320#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002321
2322/**
2323 * Parse out a swizzle mask.
2324 *
Brian Paul32df89e2005-10-29 18:26:43 +00002325 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002326 *
2327 * The len parameter allows us to grab 4 components for a vector
2328 * swizzle, or just 1 component for a scalar src register selection
2329 */
Brian Paul32df89e2005-10-29 18:26:43 +00002330static void
Brian Paula088f162006-09-05 23:08:51 +00002331parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002332{
Brian Paul32df89e2005-10-29 18:26:43 +00002333 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002334
Brian Paul32df89e2005-10-29 18:26:43 +00002335 for (i = 0; i < 4; i++)
2336 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002337
Brian Paul32df89e2005-10-29 18:26:43 +00002338 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002339 switch (*(*inst)++) {
2340 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002341 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002342 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002343 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002344 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002345 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002346 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002347 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002348 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002349 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002350 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002351 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002352 default:
2353 _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
2354 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002355 }
2356 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002357}
2358
Jouk Jansen40322e12004-04-05 08:50:36 +00002359
Brian Paul32df89e2005-10-29 18:26:43 +00002360/**
2361 * Parse an extended swizzle mask which is a sequence of
2362 * four x/y/z/w/0/1 tokens.
2363 * \return swizzle four swizzle values
2364 * \return negateMask four element bitfield
2365 */
2366static void
Brian Paula088f162006-09-05 23:08:51 +00002367parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4],
Brian Paul32df89e2005-10-29 18:26:43 +00002368 GLubyte *negateMask)
2369{
2370 GLint i;
2371
2372 *negateMask = 0x0;
2373 for (i = 0; i < 4; i++) {
2374 GLubyte swz;
2375 if (parse_sign(inst) == -1)
2376 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002377
2378 swz = *(*inst)++;
2379
2380 switch (swz) {
2381 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002382 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002383 break;
2384 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002385 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002386 break;
2387 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002388 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002389 break;
2390 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002391 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002392 break;
2393 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002394 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002395 break;
2396 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002397 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002398 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002399 default:
2400 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2401 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002402 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002403 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002404}
2405
2406
2407static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002408parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
2409 struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002410 struct arb_program *Program,
2411 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002412 GLboolean *IsRelOffset )
2413{
2414 struct var_cache *src;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002415 GLuint binding, is_generic, found;
Brian Paulbd997cd2004-07-20 21:12:56 +00002416 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002417
Keith Whitwell7c26b612005-04-21 14:46:57 +00002418 *IsRelOffset = 0;
2419
Jouk Jansen40322e12004-04-05 08:50:36 +00002420 /* And the binding for the src */
2421 switch (*(*inst)++) {
2422 case REGISTER_ATTRIB:
2423 if (parse_attrib_binding
Brian Paul18e7c5c2005-10-30 21:46:00 +00002424 (ctx, inst, Program, &binding, &is_generic))
Jouk Jansen40322e12004-04-05 08:50:36 +00002425 return 1;
2426 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002427 *Index = binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002428
2429 /* We need to insert a dummy variable into the var_cache so we can
2430 * catch generic vertex attrib aliasing errors
2431 */
2432 var_cache_create(&src);
2433 src->type = vt_attrib;
Brian Paul6a769d92006-04-28 15:42:15 +00002434 src->name = (const GLubyte *) "Dummy Attrib Variable";
Brian Paul18e7c5c2005-10-30 21:46:00 +00002435 src->attrib_binding = binding;
2436 src->attrib_is_generic = is_generic;
Jouk Jansen40322e12004-04-05 08:50:36 +00002437 var_cache_append(vc_head, src);
2438 if (generic_attrib_check(*vc_head)) {
Brian Paula088f162006-09-05 23:08:51 +00002439 program_error(ctx, Program->Position,
2440 "Cannot use both a generic vertex attribute "
2441 "and a specific attribute of the same type");
Jouk Jansen40322e12004-04-05 08:50:36 +00002442 return 1;
2443 }
2444 break;
2445
2446 case REGISTER_PARAM:
2447 switch (**inst) {
2448 case PARAM_ARRAY_ELEMENT:
2449 (*inst)++;
2450 src = parse_string (inst, vc_head, Program, &found);
2451 Program->Position = parse_position (inst);
2452
2453 if (!found) {
Brian Paula088f162006-09-05 23:08:51 +00002454 program_error(ctx, Program->Position,
2455 "2: Undefined variable"); /* src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002456 return 1;
2457 }
2458
Brian Paul95801792005-12-06 15:41:43 +00002459 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002460
2461 switch (*(*inst)++) {
2462 case ARRAY_INDEX_ABSOLUTE:
2463 offset = parse_integer (inst, Program);
2464
2465 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002466 || (offset >= (int)src->param_binding_length)) {
Brian Paula088f162006-09-05 23:08:51 +00002467 program_error(ctx, Program->Position,
2468 "Index out of range");
2469 /* offset, src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002470 return 1;
2471 }
2472
2473 *Index = src->param_binding_begin + offset;
2474 break;
2475
2476 case ARRAY_INDEX_RELATIVE:
2477 {
2478 GLint addr_reg_idx, rel_off;
2479
2480 /* First, grab the address regiseter */
2481 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2482 return 1;
2483
2484 /* And the .x */
2485 ((*inst)++);
2486 ((*inst)++);
2487 ((*inst)++);
2488 ((*inst)++);
2489
2490 /* Then the relative offset */
2491 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2492
2493 /* And store it properly */
2494 *Index = src->param_binding_begin + rel_off;
2495 *IsRelOffset = 1;
2496 }
2497 break;
2498 }
2499 break;
2500
2501 default:
Jouk Jansen40322e12004-04-05 08:50:36 +00002502 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2503 return 1;
2504
Brian Paul95801792005-12-06 15:41:43 +00002505 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002506 *Index = src->param_binding_begin;
2507 break;
2508 }
2509 break;
2510
2511 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002512 src = parse_string (inst, vc_head, Program, &found);
2513 Program->Position = parse_position (inst);
2514
2515 /* If the name has never been added to our symbol table, we're hosed */
2516 if (!found) {
Brian Paula088f162006-09-05 23:08:51 +00002517 program_error(ctx, Program->Position,
2518 "3: Undefined variable"); /* src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002519 return 1;
2520 }
2521
2522 switch (src->type) {
2523 case vt_attrib:
2524 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002525 *Index = src->attrib_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002526 break;
2527
2528 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2529 case vt_param:
Brian Paul95801792005-12-06 15:41:43 +00002530 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002531 *Index = src->param_binding_begin;
2532 break;
2533
2534 case vt_temp:
2535 *File = PROGRAM_TEMPORARY;
2536 *Index = src->temp_binding;
2537 break;
2538
2539 /* If the var type is vt_output no go */
2540 default:
Brian Paula088f162006-09-05 23:08:51 +00002541 program_error(ctx, Program->Position,
2542 "destination register is read only");
2543 /* bad src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002544 return 1;
2545 }
2546 break;
2547
2548 default:
Brian Paula088f162006-09-05 23:08:51 +00002549 program_error(ctx, Program->Position,
2550 "Unknown token in parse_src_reg");
Jouk Jansen40322e12004-04-05 08:50:36 +00002551 return 1;
2552 }
2553
2554 return 0;
2555}
2556
2557/**
Brian Paul18e7c5c2005-10-30 21:46:00 +00002558 * Parse fragment program vector source register.
Jouk Jansen40322e12004-04-05 08:50:36 +00002559 */
2560static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002561parse_fp_vector_src_reg(GLcontext * ctx, const GLubyte ** inst,
Brian Paul32df89e2005-10-29 18:26:43 +00002562 struct var_cache **vc_head,
2563 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00002564 struct prog_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002565{
Brian Paul7aebaf32005-10-30 21:23:23 +00002566 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002567 GLint index;
2568 GLboolean negate;
2569 GLubyte swizzle[4];
2570 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002571
Jouk Jansen40322e12004-04-05 08:50:36 +00002572 /* Grab the sign */
Brian Paul32df89e2005-10-29 18:26:43 +00002573 negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002574
2575 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002576 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002577 return 1;
2578
2579 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002580 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002581
Brian Paul32df89e2005-10-29 18:26:43 +00002582 reg->File = file;
2583 reg->Index = index;
Brian Paul32df89e2005-10-29 18:26:43 +00002584 reg->NegateBase = negate;
2585 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00002586 return 0;
2587}
2588
Jouk Jansen40322e12004-04-05 08:50:36 +00002589
Brian Paulb7fc1c32006-08-30 23:38:03 +00002590/**
2591 * Parse fragment program destination register.
2592 * \return 1 if error, 0 if no error.
2593 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002594static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002595parse_fp_dst_reg(GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00002596 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002597 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002598{
Brian Paul7aebaf32005-10-30 21:23:23 +00002599 GLint mask;
2600 GLuint idx;
2601 enum register_file file;
2602
Keith Whitwell7c26b612005-04-21 14:46:57 +00002603 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002604 return 1;
2605
Keith Whitwell7c26b612005-04-21 14:46:57 +00002606 reg->File = file;
2607 reg->Index = idx;
2608 reg->WriteMask = mask;
2609 return 0;
2610}
2611
2612
Brian Paul7aebaf32005-10-30 21:23:23 +00002613/**
2614 * Parse fragment program scalar src register.
Brian Paulb7fc1c32006-08-30 23:38:03 +00002615 * \return 1 if error, 0 if no error.
Brian Paul7aebaf32005-10-30 21:23:23 +00002616 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002617static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002618parse_fp_scalar_src_reg (GLcontext * ctx, const GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00002619 struct var_cache **vc_head,
2620 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002621 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002622{
Brian Paul7aebaf32005-10-30 21:23:23 +00002623 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002624 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00002625 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002626 GLubyte Swizzle[4];
2627 GLboolean IsRelOffset;
2628
2629 /* Grab the sign */
2630 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2631
2632 /* And the src reg */
2633 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2634 return 1;
2635
2636 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002637 parse_swizzle_mask(inst, Swizzle, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002638
Keith Whitwell7c26b612005-04-21 14:46:57 +00002639 reg->File = File;
2640 reg->Index = Index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002641 reg->NegateBase = Negate;
2642 reg->Swizzle = (Swizzle[0] << 0);
2643
Jouk Jansen40322e12004-04-05 08:50:36 +00002644 return 0;
2645}
2646
Keith Whitwell7c26b612005-04-21 14:46:57 +00002647
Jouk Jansen40322e12004-04-05 08:50:36 +00002648/**
2649 * This is a big mother that handles getting opcodes into the instruction
2650 * and handling the src & dst registers for fragment program instructions
Brian Paulb7fc1c32006-08-30 23:38:03 +00002651 * \return 1 if error, 0 if no error
Jouk Jansen40322e12004-04-05 08:50:36 +00002652 */
2653static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002654parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002655 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002656 struct prog_instruction *fp)
Jouk Jansen40322e12004-04-05 08:50:36 +00002657{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002658 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002659 GLuint texcoord;
2660 GLubyte instClass, type, code;
2661 GLboolean rel;
2662
Brian Pauld6272e02006-10-29 18:03:16 +00002663 _mesa_init_instructions(fp, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002664
2665 /* Record the position in the program string for debugging */
2666 fp->StringPos = Program->Position;
2667
2668 /* OP_ALU_INST or OP_TEX_INST */
2669 instClass = *(*inst)++;
2670
2671 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2672 * OP_TEX_{SAMPLE, KIL}
2673 */
2674 type = *(*inst)++;
2675
2676 /* The actual opcode name */
2677 code = *(*inst)++;
2678
2679 /* Increment the correct count */
2680 switch (instClass) {
2681 case OP_ALU_INST:
2682 Program->NumAluInstructions++;
2683 break;
2684 case OP_TEX_INST:
2685 Program->NumTexInstructions++;
2686 break;
2687 }
2688
Jouk Jansen40322e12004-04-05 08:50:36 +00002689 switch (type) {
2690 case OP_ALU_VECTOR:
2691 switch (code) {
2692 case OP_ABS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002693 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002694 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00002695 fp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002696 break;
2697
2698 case OP_FLR_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002699 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002700 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00002701 fp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00002702 break;
2703
2704 case OP_FRC_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002705 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002706 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00002707 fp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00002708 break;
2709
2710 case OP_LIT_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002711 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002712 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00002713 fp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002714 break;
2715
2716 case OP_MOV_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002717 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002718 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00002719 fp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00002720 break;
2721 }
2722
Keith Whitwell7c26b612005-04-21 14:46:57 +00002723 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002724 return 1;
2725
Keith Whitwell7c26b612005-04-21 14:46:57 +00002726 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002727 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002728 break;
2729
2730 case OP_ALU_SCALAR:
2731 switch (code) {
2732 case OP_COS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002733 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002734 case OP_COS:
Brian Paul7e807512005-11-05 17:10:45 +00002735 fp->Opcode = OPCODE_COS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002736 break;
2737
2738 case OP_EX2_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002739 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002740 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00002741 fp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002742 break;
2743
2744 case OP_LG2_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002745 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002746 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00002747 fp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002748 break;
2749
2750 case OP_RCP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002751 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002752 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00002753 fp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002754 break;
2755
2756 case OP_RSQ_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002757 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002758 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00002759 fp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002760 break;
2761
2762 case OP_SIN_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002763 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002764 case OP_SIN:
Brian Paul7e807512005-11-05 17:10:45 +00002765 fp->Opcode = OPCODE_SIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002766 break;
2767
2768 case OP_SCS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002769 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002770 case OP_SCS:
2771
Brian Paul7e807512005-11-05 17:10:45 +00002772 fp->Opcode = OPCODE_SCS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002773 break;
2774 }
2775
Keith Whitwell7c26b612005-04-21 14:46:57 +00002776 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002777 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002778
2779 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002780 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002781 break;
2782
2783 case OP_ALU_BINSC:
2784 switch (code) {
2785 case OP_POW_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002786 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002787 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00002788 fp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00002789 break;
2790 }
2791
Keith Whitwell7c26b612005-04-21 14:46:57 +00002792 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002793 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002794
Jouk Jansen40322e12004-04-05 08:50:36 +00002795 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002796 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002797 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002798 }
2799 break;
2800
2801
2802 case OP_ALU_BIN:
2803 switch (code) {
2804 case OP_ADD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002805 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002806 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00002807 fp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002808 break;
2809
2810 case OP_DP3_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002811 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002812 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00002813 fp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00002814 break;
2815
2816 case OP_DP4_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002817 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002818 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00002819 fp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00002820 break;
2821
2822 case OP_DPH_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002823 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002824 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00002825 fp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00002826 break;
2827
2828 case OP_DST_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002829 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002830 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00002831 fp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00002832 break;
2833
2834 case OP_MAX_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002835 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002836 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00002837 fp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002838 break;
2839
2840 case OP_MIN_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002841 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002842 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00002843 fp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002844 break;
2845
2846 case OP_MUL_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002847 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002848 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00002849 fp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00002850 break;
2851
2852 case OP_SGE_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002853 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002854 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00002855 fp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002856 break;
2857
2858 case OP_SLT_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002859 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002860 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00002861 fp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002862 break;
2863
2864 case OP_SUB_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002865 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002866 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00002867 fp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002868 break;
2869
2870 case OP_XPD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002871 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002872 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00002873 fp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002874 break;
2875 }
2876
Keith Whitwell7c26b612005-04-21 14:46:57 +00002877 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002878 return 1;
2879 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002880 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2881 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002882 }
2883 break;
2884
2885 case OP_ALU_TRI:
2886 switch (code) {
2887 case OP_CMP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002888 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002889 case OP_CMP:
Brian Paul7e807512005-11-05 17:10:45 +00002890 fp->Opcode = OPCODE_CMP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002891 break;
2892
2893 case OP_LRP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002894 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002895 case OP_LRP:
Brian Paul7e807512005-11-05 17:10:45 +00002896 fp->Opcode = OPCODE_LRP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002897 break;
2898
2899 case OP_MAD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002900 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002901 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00002902 fp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002903 break;
2904 }
2905
Keith Whitwell7c26b612005-04-21 14:46:57 +00002906 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002907 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002908
Jouk Jansen40322e12004-04-05 08:50:36 +00002909 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002910 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2911 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002912 }
2913 break;
2914
2915 case OP_ALU_SWZ:
2916 switch (code) {
2917 case OP_SWZ_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002918 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002919 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00002920 fp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002921 break;
2922 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00002923 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002924 return 1;
2925
Keith Whitwell7c26b612005-04-21 14:46:57 +00002926 {
Brian Paul32df89e2005-10-29 18:26:43 +00002927 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002928 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002929 enum register_file file;
2930 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002931
Brian Paul32df89e2005-10-29 18:26:43 +00002932 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002933 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00002934 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
2935 fp->SrcReg[0].File = file;
2936 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00002937 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002938 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
2939 swizzle[1],
2940 swizzle[2],
2941 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00002942 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002943 break;
2944
2945 case OP_TEX_SAMPLE:
2946 switch (code) {
2947 case OP_TEX_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002948 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002949 case OP_TEX:
Brian Paul7e807512005-11-05 17:10:45 +00002950 fp->Opcode = OPCODE_TEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002951 break;
2952
2953 case OP_TXP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002954 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002955 case OP_TXP:
Brian Paul7e807512005-11-05 17:10:45 +00002956 fp->Opcode = OPCODE_TXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002957 break;
2958
2959 case OP_TXB_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002960 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002961 case OP_TXB:
Brian Paul7e807512005-11-05 17:10:45 +00002962 fp->Opcode = OPCODE_TXB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002963 break;
2964 }
2965
Keith Whitwell7c26b612005-04-21 14:46:57 +00002966 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002967 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002968
2969 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002970 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002971
2972 /* texImageUnit */
2973 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
2974 return 1;
2975 fp->TexSrcUnit = texcoord;
2976
2977 /* texTarget */
2978 switch (*(*inst)++) {
2979 case TEXTARGET_1D:
Brian Paul7e807512005-11-05 17:10:45 +00002980 fp->TexSrcTarget = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002981 break;
2982 case TEXTARGET_2D:
Brian Paul7e807512005-11-05 17:10:45 +00002983 fp->TexSrcTarget = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002984 break;
2985 case TEXTARGET_3D:
Brian Paul7e807512005-11-05 17:10:45 +00002986 fp->TexSrcTarget = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002987 break;
2988 case TEXTARGET_RECT:
Brian Paul7e807512005-11-05 17:10:45 +00002989 fp->TexSrcTarget = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002990 break;
2991 case TEXTARGET_CUBE:
Brian Paul7e807512005-11-05 17:10:45 +00002992 fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002993 break;
2994 case TEXTARGET_SHADOW1D:
2995 case TEXTARGET_SHADOW2D:
2996 case TEXTARGET_SHADOWRECT:
2997 /* TODO ARB_fragment_program_shadow code */
2998 break;
Ian Romanickbb372f12007-05-16 15:34:22 -07002999 case TEXTARGET_1D_ARRAY:
3000 fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
3001 break;
3002 case TEXTARGET_2D_ARRAY:
3003 fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
3004 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003005 }
Brian Paulb7fc1c32006-08-30 23:38:03 +00003006 Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
3007 /* Check that both "2D" and "CUBE" (for example) aren't both used */
3008 if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
Brian Paula088f162006-09-05 23:08:51 +00003009 program_error(ctx, Program->Position,
3010 "multiple targets used on one texture image unit");
Brian Paulb7fc1c32006-08-30 23:38:03 +00003011 return 1;
3012 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003013 break;
3014
3015 case OP_TEX_KIL:
Keith Whitwellc3626a92005-11-01 17:25:49 +00003016 Program->UsesKill = 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003017 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003018 return 1;
Brian Paul7e807512005-11-05 17:10:45 +00003019 fp->Opcode = OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003020 break;
Brian Paulb7fc1c32006-08-30 23:38:03 +00003021 default:
3022 _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type);
3023 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003024 }
3025
3026 return 0;
3027}
3028
Keith Whitwell7c26b612005-04-21 14:46:57 +00003029static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003030parse_vp_dst_reg(GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00003031 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003032 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003033{
Brian Paul7aebaf32005-10-30 21:23:23 +00003034 GLint mask;
3035 GLuint idx;
3036 enum register_file file;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003037
3038 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3039 return 1;
3040
3041 reg->File = file;
3042 reg->Index = idx;
3043 reg->WriteMask = mask;
3044 return 0;
3045}
3046
3047/**
3048 * Handle the parsing out of a masked address register
3049 *
3050 * \param Index - The register index we write to
3051 * \param WriteMask - The mask controlling which components we write (1->write)
3052 *
3053 * \return 0 on sucess, 1 on error
3054 */
3055static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003056parse_vp_address_reg (GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00003057 struct var_cache **vc_head,
3058 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003059 struct prog_dst_register *reg)
Keith Whitwell7c26b612005-04-21 14:46:57 +00003060{
3061 GLint idx;
3062
3063 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3064 return 1;
3065
3066 /* This should be 0x8 */
3067 (*inst)++;
3068
3069 reg->File = PROGRAM_ADDRESS;
3070 reg->Index = idx;
3071
3072 /* Writemask of .x is implied */
3073 reg->WriteMask = 0x1;
3074 return 0;
3075}
3076
3077/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003078 * Parse vertex program vector source register.
Keith Whitwell7c26b612005-04-21 14:46:57 +00003079 */
3080static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003081parse_vp_vector_src_reg(GLcontext * ctx, const GLubyte ** inst,
Brian Paul32df89e2005-10-29 18:26:43 +00003082 struct var_cache **vc_head,
3083 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00003084 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003085{
Brian Paul7aebaf32005-10-30 21:23:23 +00003086 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00003087 GLint index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003088 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003089 GLubyte swizzle[4];
3090 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003091
3092 /* Grab the sign */
Brian Paul7aebaf32005-10-30 21:23:23 +00003093 negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003094
3095 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00003096 if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003097 return 1;
3098
3099 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003100 parse_swizzle_mask(inst, swizzle, 4);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003101
Brian Paul32df89e2005-10-29 18:26:43 +00003102 reg->File = file;
3103 reg->Index = index;
3104 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
3105 swizzle[2], swizzle[3]);
Brian Paul7e807512005-11-05 17:10:45 +00003106 reg->NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003107 reg->RelAddr = isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003108 return 0;
3109}
3110
3111
3112static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003113parse_vp_scalar_src_reg (GLcontext * ctx, const GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00003114 struct var_cache **vc_head,
3115 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003116 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003117{
Brian Paul7aebaf32005-10-30 21:23:23 +00003118 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003119 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003120 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003121 GLubyte Swizzle[4];
3122 GLboolean IsRelOffset;
3123
3124 /* Grab the sign */
3125 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3126
3127 /* And the src reg */
3128 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3129 return 1;
3130
3131 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003132 parse_swizzle_mask(inst, Swizzle, 1);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003133
3134 reg->File = File;
3135 reg->Index = Index;
3136 reg->Swizzle = (Swizzle[0] << 0);
Brian Paul7e807512005-11-05 17:10:45 +00003137 reg->NegateBase = Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003138 reg->RelAddr = IsRelOffset;
3139 return 0;
3140}
3141
3142
Jouk Jansen40322e12004-04-05 08:50:36 +00003143/**
3144 * This is a big mother that handles getting opcodes into the instruction
3145 * and handling the src & dst registers for vertex program instructions
3146 */
3147static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003148parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00003149 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003150 struct prog_instruction *vp)
Jouk Jansen40322e12004-04-05 08:50:36 +00003151{
3152 GLint a;
3153 GLubyte type, code;
3154
3155 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3156 type = *(*inst)++;
3157
3158 /* The actual opcode name */
3159 code = *(*inst)++;
3160
Brian Pauld6272e02006-10-29 18:03:16 +00003161 _mesa_init_instructions(vp, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003162 /* Record the position in the program string for debugging */
3163 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003164
3165 switch (type) {
3166 /* XXX: */
3167 case OP_ALU_ARL:
Brian Paul7e807512005-11-05 17:10:45 +00003168 vp->Opcode = OPCODE_ARL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003169
3170 /* Remember to set SrcReg.RelAddr; */
3171
3172 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003173 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003174 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003175
Jouk Jansen40322e12004-04-05 08:50:36 +00003176 vp->DstReg.File = PROGRAM_ADDRESS;
3177
3178 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003179 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003180 return 1;
3181
3182 break;
3183
3184 case OP_ALU_VECTOR:
3185 switch (code) {
3186 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00003187 vp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00003188 break;
3189 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00003190 vp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00003191 break;
3192 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00003193 vp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00003194 break;
3195 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00003196 vp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003197 break;
3198 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00003199 vp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00003200 break;
3201 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003202
3203 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003204 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003205
3206 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003207 return 1;
3208 break;
3209
3210 case OP_ALU_SCALAR:
3211 switch (code) {
3212 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00003213 vp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003214 break;
3215 case OP_EXP:
Brian Paul7e807512005-11-05 17:10:45 +00003216 vp->Opcode = OPCODE_EXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003217 break;
3218 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00003219 vp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003220 break;
3221 case OP_LOG:
Brian Paul7e807512005-11-05 17:10:45 +00003222 vp->Opcode = OPCODE_LOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00003223 break;
3224 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00003225 vp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003226 break;
3227 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00003228 vp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003229 break;
3230 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003231 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003232 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003233
3234 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003235 return 1;
3236 break;
3237
3238 case OP_ALU_BINSC:
3239 switch (code) {
3240 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00003241 vp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00003242 break;
3243 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003244 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003245 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003246
Jouk Jansen40322e12004-04-05 08:50:36 +00003247 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003248 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003249 return 1;
3250 }
3251 break;
3252
3253 case OP_ALU_BIN:
3254 switch (code) {
3255 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00003256 vp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003257 break;
3258 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00003259 vp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00003260 break;
3261 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00003262 vp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00003263 break;
3264 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00003265 vp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00003266 break;
3267 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00003268 vp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00003269 break;
3270 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00003271 vp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003272 break;
3273 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00003274 vp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00003275 break;
3276 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00003277 vp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003278 break;
3279 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00003280 vp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003281 break;
3282 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00003283 vp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003284 break;
3285 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00003286 vp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003287 break;
3288 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00003289 vp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003290 break;
3291 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003292 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003293 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003294
Jouk Jansen40322e12004-04-05 08:50:36 +00003295 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003296 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003297 return 1;
3298 }
3299 break;
3300
3301 case OP_ALU_TRI:
3302 switch (code) {
3303 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00003304 vp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003305 break;
3306 }
3307
Keith Whitwell7c26b612005-04-21 14:46:57 +00003308 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003309 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003310
Jouk Jansen40322e12004-04-05 08:50:36 +00003311 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003312 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003313 return 1;
3314 }
3315 break;
3316
3317 case OP_ALU_SWZ:
3318 switch (code) {
3319 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00003320 vp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003321 break;
3322 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003323 {
Brian Paul32df89e2005-10-29 18:26:43 +00003324 GLubyte swizzle[4];
3325 GLubyte negateMask;
3326 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003327 enum register_file file;
3328 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003329
Keith Whitwell7c26b612005-04-21 14:46:57 +00003330 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3331 return 1;
3332
Brian Paul32df89e2005-10-29 18:26:43 +00003333 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003334 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003335 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3336 vp->SrcReg[0].File = file;
3337 vp->SrcReg[0].Index = index;
Brian Paul7e807512005-11-05 17:10:45 +00003338 vp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003339 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3340 swizzle[1],
3341 swizzle[2],
3342 swizzle[3]);
3343 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003344 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003345 break;
3346 }
3347 return 0;
3348}
3349
3350#if DEBUG_PARSING
3351
3352static GLvoid
Jouk Jansen40322e12004-04-05 08:50:36 +00003353debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3354 struct arb_program *Program)
3355{
3356 struct var_cache *vc;
3357 GLint a, b;
3358
Brianb618ac82007-02-22 09:39:25 -07003359 fprintf (stderr, "debug_variables, vc_head: %p\n", (void*) vc_head);
Jouk Jansen40322e12004-04-05 08:50:36 +00003360
3361 /* First of all, print out the contents of the var_cache */
3362 vc = vc_head;
3363 while (vc) {
Brianb618ac82007-02-22 09:39:25 -07003364 fprintf (stderr, "[%p]\n", (void*) vc);
Jouk Jansen40322e12004-04-05 08:50:36 +00003365 switch (vc->type) {
3366 case vt_none:
3367 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3368 break;
3369 case vt_attrib:
3370 fprintf (stderr, "ATTRIB %s\n", vc->name);
3371 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3372 break;
3373 case vt_param:
3374 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3375 vc->param_binding_begin, vc->param_binding_length);
3376 b = vc->param_binding_begin;
3377 for (a = 0; a < vc->param_binding_length; a++) {
3378 fprintf (stderr, "%s\n",
Brianb618ac82007-02-22 09:39:25 -07003379 Program->Base.Parameters->Parameters[a + b].Name);
3380 if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
3381 const char *s;
3382 s = _mesa_program_state_string(Program->Base.Parameters->Parameters
3383 [a + b].StateIndexes);
3384 fprintf(stderr, "%s\n", s);
3385 _mesa_free((char *) s);
Jouk Jansen40322e12004-04-05 08:50:36 +00003386 }
3387 else
3388 fprintf (stderr, "%f %f %f %f\n",
Brianb618ac82007-02-22 09:39:25 -07003389 Program->Base.Parameters->ParameterValues[a + b][0],
3390 Program->Base.Parameters->ParameterValues[a + b][1],
3391 Program->Base.Parameters->ParameterValues[a + b][2],
3392 Program->Base.Parameters->ParameterValues[a + b][3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003393 }
3394 break;
3395 case vt_temp:
3396 fprintf (stderr, "TEMP %s\n", vc->name);
3397 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3398 break;
3399 case vt_output:
3400 fprintf (stderr, "OUTPUT %s\n", vc->name);
3401 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3402 break;
3403 case vt_alias:
3404 fprintf (stderr, "ALIAS %s\n", vc->name);
Brianb618ac82007-02-22 09:39:25 -07003405 fprintf (stderr, " binding: 0x%p (%s)\n",
3406 (void*) vc->alias_binding, vc->alias_binding->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00003407 break;
Brianb618ac82007-02-22 09:39:25 -07003408 default:
3409 /* nothing */
3410 ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003411 }
3412 vc = vc->next;
3413 }
3414}
3415
Brian Paul72030e02005-11-03 03:30:34 +00003416#endif /* DEBUG_PARSING */
Brian Paul7aebaf32005-10-30 21:23:23 +00003417
3418
3419/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003420 * The main loop for parsing a fragment or vertex program
3421 *
Brian Paul72030e02005-11-03 03:30:34 +00003422 * \return 1 on error, 0 on success
Jouk Jansen40322e12004-04-05 08:50:36 +00003423 */
Brian Paul72030e02005-11-03 03:30:34 +00003424static GLint
Brian Paula088f162006-09-05 23:08:51 +00003425parse_instructions(GLcontext * ctx, const GLubyte * inst,
3426 struct var_cache **vc_head, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003427{
Brian Paul72030e02005-11-03 03:30:34 +00003428 const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
3429 ? ctx->Const.FragmentProgram.MaxInstructions
3430 : ctx->Const.VertexProgram.MaxInstructions;
Jouk Jansen40322e12004-04-05 08:50:36 +00003431 GLint err = 0;
3432
Brian Paul72030e02005-11-03 03:30:34 +00003433 ASSERT(MAX_INSTRUCTIONS >= maxInst);
3434
Jouk Jansen40322e12004-04-05 08:50:36 +00003435 Program->MajorVersion = (GLuint) * inst++;
3436 Program->MinorVersion = (GLuint) * inst++;
3437
3438 while (*inst != END) {
3439 switch (*inst++) {
3440
3441 case OPTION:
3442 switch (*inst++) {
3443 case ARB_PRECISION_HINT_FASTEST:
3444 Program->PrecisionOption = GL_FASTEST;
3445 break;
3446
3447 case ARB_PRECISION_HINT_NICEST:
3448 Program->PrecisionOption = GL_NICEST;
3449 break;
3450
3451 case ARB_FOG_EXP:
3452 Program->FogOption = GL_EXP;
3453 break;
3454
3455 case ARB_FOG_EXP2:
3456 Program->FogOption = GL_EXP2;
3457 break;
3458
3459 case ARB_FOG_LINEAR:
3460 Program->FogOption = GL_LINEAR;
3461 break;
3462
3463 case ARB_POSITION_INVARIANT:
3464 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
Brian Paul45cd2f92005-11-03 02:25:10 +00003465 Program->HintPositionInvariant = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003466 break;
3467
3468 case ARB_FRAGMENT_PROGRAM_SHADOW:
3469 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3470 /* TODO ARB_fragment_program_shadow code */
3471 }
3472 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003473
3474 case ARB_DRAW_BUFFERS:
3475 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3476 /* do nothing for now */
3477 }
3478 break;
Ian Romanickbb372f12007-05-16 15:34:22 -07003479
3480 case MESA_TEXTURE_ARRAY:
3481 /* do nothing for now */
3482 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003483 }
3484 break;
3485
3486 case INSTRUCTION:
Brian Paul72030e02005-11-03 03:30:34 +00003487 /* check length */
3488 if (Program->Base.NumInstructions + 1 >= maxInst) {
Brian Paula088f162006-09-05 23:08:51 +00003489 program_error(ctx, Program->Position,
3490 "Max instruction count exceeded");
Brian Paul72030e02005-11-03 03:30:34 +00003491 return 1;
3492 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003493 Program->Position = parse_position (&inst);
Brian Paul72030e02005-11-03 03:30:34 +00003494 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003495 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003496 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul8c41a142005-11-19 15:36:28 +00003497 &Program->Base.Instructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003498 }
3499 else {
Jouk Jansen40322e12004-04-05 08:50:36 +00003500 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul8c41a142005-11-19 15:36:28 +00003501 &Program->Base.Instructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003502 }
3503
Brian Paul72030e02005-11-03 03:30:34 +00003504 /* increment instuction count */
Jouk Jansen40322e12004-04-05 08:50:36 +00003505 Program->Base.NumInstructions++;
3506 break;
3507
3508 case DECLARATION:
3509 err = parse_declaration (ctx, &inst, vc_head, Program);
3510 break;
3511
3512 default:
3513 break;
3514 }
3515
3516 if (err)
3517 break;
3518 }
3519
3520 /* Finally, tag on an OPCODE_END instruction */
Brian Paul8c41a142005-11-19 15:36:28 +00003521 {
Brian Paul7aebaf32005-10-30 21:23:23 +00003522 const GLuint numInst = Program->Base.NumInstructions;
Brian Pauld6272e02006-10-29 18:03:16 +00003523 _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
Brian Paul8c41a142005-11-19 15:36:28 +00003524 Program->Base.Instructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003525 /* YYY Wrong Position in program, whatever, at least not random -> crash
3526 Program->Position = parse_position (&inst);
3527 */
Brian Paul8c41a142005-11-19 15:36:28 +00003528 Program->Base.Instructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003529 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003530 Program->Base.NumInstructions++;
3531
Brian Paul05051032005-11-01 04:36:33 +00003532 /*
3533 * Initialize native counts to logical counts. The device driver may
3534 * change them if program is translated into a hardware program.
3535 */
3536 Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
3537 Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
3538 Program->Base.NumNativeParameters = Program->Base.NumParameters;
3539 Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
3540 Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
Brian Paul05051032005-11-01 04:36:33 +00003541
Jouk Jansen40322e12004-04-05 08:50:36 +00003542 return err;
3543}
3544
Brian Paul7aebaf32005-10-30 21:23:23 +00003545
Jouk Jansen40322e12004-04-05 08:50:36 +00003546/* XXX temporary */
Brian5cc12922006-12-14 14:27:05 -07003547LONGSTRING static char core_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +00003548#include "grammar_syn.h"
3549;
3550
Brian Paul7aebaf32005-10-30 21:23:23 +00003551
Brian Paul8c41a142005-11-19 15:36:28 +00003552/**
3553 * Set a grammar parameter.
3554 * \param name the grammar parameter
3555 * \param value the new parameter value
3556 * \return 0 if OK, 1 if error
3557 */
3558static int
3559set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value)
Jouk Jansen40322e12004-04-05 08:50:36 +00003560{
3561 char error_msg[300];
3562 GLint error_pos;
3563
Brian Paul8c41a142005-11-19 15:36:28 +00003564 if (grammar_set_reg8 (id, (const byte *) name, value))
Jouk Jansen40322e12004-04-05 08:50:36 +00003565 return 0;
3566
3567 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3568 _mesa_set_program_error (ctx, error_pos, error_msg);
3569 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3570 return 1;
3571}
3572
Brian Paul8c41a142005-11-19 15:36:28 +00003573
3574/**
3575 * Enable support for the given language option in the parser.
3576 * \return 1 if OK, 0 if error
3577 */
3578static int
3579enable_ext(GLcontext *ctx, grammar id, const char *name)
Jouk Jansen40322e12004-04-05 08:50:36 +00003580{
Brian Paul8c41a142005-11-19 15:36:28 +00003581 return !set_reg8(ctx, id, name, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003582}
3583
Brian Paul8c41a142005-11-19 15:36:28 +00003584
3585/**
3586 * Enable parser extensions based on which OpenGL extensions are supported
3587 * by this rendering context.
3588 *
3589 * \return GL_TRUE if OK, GL_FALSE if error.
3590 */
3591static GLboolean
3592enable_parser_extensions(GLcontext *ctx, grammar id)
Jouk Jansen40322e12004-04-05 08:50:36 +00003593{
Brian Paul8c41a142005-11-19 15:36:28 +00003594#if 0
3595 /* These are not supported at this time */
3596 if ((ctx->Extensions.ARB_vertex_blend ||
3597 ctx->Extensions.EXT_vertex_weighting)
Brian Paul43cc1dc2006-09-05 23:11:09 +00003598 && !enable_ext(ctx, id, "vertex_blend"))
Brian Paul8c41a142005-11-19 15:36:28 +00003599 return GL_FALSE;
3600 if (ctx->Extensions.ARB_matrix_palette
3601 && !enable_ext(ctx, id, "matrix_palette"))
3602 return GL_FALSE;
3603 if (ctx->Extensions.ARB_fragment_program_shadow
3604 && !enable_ext(ctx, id, "fragment_program_shadow"))
3605 return GL_FALSE;
3606#endif
3607 if (ctx->Extensions.EXT_point_parameters
3608 && !enable_ext(ctx, id, "point_parameters"))
3609 return GL_FALSE;
3610 if (ctx->Extensions.EXT_secondary_color
3611 && !enable_ext(ctx, id, "secondary_color"))
3612 return GL_FALSE;
3613 if (ctx->Extensions.EXT_fog_coord
3614 && !enable_ext(ctx, id, "fog_coord"))
3615 return GL_FALSE;
3616 if (ctx->Extensions.NV_texture_rectangle
3617 && !enable_ext(ctx, id, "texture_rectangle"))
3618 return GL_FALSE;
3619 if (ctx->Extensions.ARB_draw_buffers
3620 && !enable_ext(ctx, id, "draw_buffers"))
3621 return GL_FALSE;
Ian Romanickbb372f12007-05-16 15:34:22 -07003622 if (ctx->Extensions.MESA_texture_array
3623 && !enable_ext(ctx, id, "texture_array"))
3624 return GL_FALSE;
Brian Paul3a557502006-09-05 23:15:29 +00003625#if 1
3626 /* hack for Warcraft (see bug 8060) */
3627 enable_ext(ctx, id, "vertex_blend");
3628#endif
3629
Brian Paul8c41a142005-11-19 15:36:28 +00003630 return GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003631}
3632
Brian Paul8c41a142005-11-19 15:36:28 +00003633
Jouk Jansen40322e12004-04-05 08:50:36 +00003634/**
3635 * This kicks everything off.
3636 *
3637 * \param ctx - The GL Context
3638 * \param str - The program string
3639 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003640 * \param program - The arb_program struct to return all the parsed info in
3641 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003642 */
Brian Paul8c41a142005-11-19 15:36:28 +00003643static GLboolean
3644_mesa_parse_arb_program(GLcontext *ctx, GLenum target,
3645 const GLubyte *str, GLsizei len,
3646 struct arb_program *program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003647{
3648 GLint a, err, error_pos;
3649 char error_msg[300];
3650 GLuint parsed_len;
3651 struct var_cache *vc_head;
3652 grammar arbprogram_syn_id;
3653 GLubyte *parsed, *inst;
3654 GLubyte *strz = NULL;
3655 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3656
Brian Paul8c41a142005-11-19 15:36:28 +00003657 /* set the program target before parsing */
3658 program->Base.Target = target;
3659
Brian Paul7f76b8f2004-09-10 01:05:39 +00003660 /* Reset error state */
3661 _mesa_set_program_error(ctx, -1, NULL);
3662
Brian Paul8c41a142005-11-19 15:36:28 +00003663 /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */
Jouk Jansen40322e12004-04-05 08:50:36 +00003664 if (!arbprogram_syn_is_ok) {
Brian Paul8c41a142005-11-19 15:36:28 +00003665 /* One-time initialization of parsing system */
Jouk Jansen40322e12004-04-05 08:50:36 +00003666 grammar grammar_syn_id;
Jouk Jansen40322e12004-04-05 08:50:36 +00003667 GLuint parsed_len;
Jouk Jansen40322e12004-04-05 08:50:36 +00003668
3669 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3670 if (grammar_syn_id == 0) {
3671 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
Brian Paul8c41a142005-11-19 15:36:28 +00003672 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003673 _mesa_set_program_error (ctx, error_pos, error_msg);
3674 _mesa_error (ctx, GL_INVALID_OPERATION,
Brian Paul8c41a142005-11-19 15:36:28 +00003675 "glProgramStringARB(Error loading grammar rule set)");
Brian Paul45703642005-10-29 15:52:31 +00003676 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003677 }
3678
Brian Paul8c41a142005-11-19 15:36:28 +00003679 err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text,
3680 &parsed, &parsed_len);
Jouk Jansen40322e12004-04-05 08:50:36 +00003681
Brian Paul49a80ca2006-04-28 15:40:11 +00003682 /* 'parsed' is unused here */
3683 _mesa_free (parsed);
3684 parsed = NULL;
3685
Brian Paul45703642005-10-29 15:52:31 +00003686 /* NOTE: we can't destroy grammar_syn_id right here because
3687 * grammar_destroy() can reset the last error
3688 */
Brian Paul8c41a142005-11-19 15:36:28 +00003689 if (err) {
3690 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003691 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3692 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul8c41a142005-11-19 15:36:28 +00003693 _mesa_error (ctx, GL_INVALID_OPERATION,
3694 "glProgramString(Error loading grammar rule set");
Jouk Jansen40322e12004-04-05 08:50:36 +00003695 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003696 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003697 }
3698
3699 grammar_destroy (grammar_syn_id);
3700
3701 arbprogram_syn_is_ok = 1;
3702 }
3703
3704 /* create the grammar object */
3705 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3706 if (arbprogram_syn_id == 0) {
Brian Paul8c41a142005-11-19 15:36:28 +00003707 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003708 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3709 _mesa_set_program_error (ctx, error_pos, error_msg);
3710 _mesa_error (ctx, GL_INVALID_OPERATION,
Brian Paul8c41a142005-11-19 15:36:28 +00003711 "glProgramString(Error loading grammer rule set)");
Brian Paul45703642005-10-29 15:52:31 +00003712 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003713 }
3714
3715 /* Set program_target register value */
Brian Paul55194df2005-11-19 23:29:18 +00003716 if (set_reg8 (ctx, arbprogram_syn_id, "program_target",
Jouk Jansen40322e12004-04-05 08:50:36 +00003717 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3718 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003719 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003720 }
3721
Brian Paul8c41a142005-11-19 15:36:28 +00003722 if (!enable_parser_extensions(ctx, arbprogram_syn_id)) {
3723 grammar_destroy(arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003724 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003725 }
3726
3727 /* check for NULL character occurences */
3728 {
Brian Paul8c41a142005-11-19 15:36:28 +00003729 GLint i;
3730 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003731 if (str[i] == '\0') {
Brian Paula088f162006-09-05 23:08:51 +00003732 program_error(ctx, i, "illegal character");
Jouk Jansen40322e12004-04-05 08:50:36 +00003733 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003734 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003735 }
Brian Paul8c41a142005-11-19 15:36:28 +00003736 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003737 }
3738
3739 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003740 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003741 if (!strz) {
Brian Paul8c41a142005-11-19 15:36:28 +00003742 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
3743 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003744 return GL_FALSE;
3745 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003746 _mesa_memcpy (strz, str, len);
3747 strz[len] = '\0';
3748
Michal Krolb80bc052004-10-21 14:09:54 +00003749 /* do a fast check on program string - initial production buffer is 4K */
Brian Paul8c41a142005-11-19 15:36:28 +00003750 err = !grammar_fast_check(arbprogram_syn_id, strz,
3751 &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00003752
3753 /* Syntax parse error */
Brian Paul8c41a142005-11-19 15:36:28 +00003754 if (err) {
Brian Paula088f162006-09-05 23:08:51 +00003755 grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos);
3756 program_error(ctx, error_pos, error_msg);
Brian Paul5fe90292004-07-20 21:15:13 +00003757
Brian Paulb3aefd12005-09-19 20:12:32 +00003758#if DEBUG_PARSING
Brian Paula088f162006-09-05 23:08:51 +00003759 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00003760 do {
Brian Paul5fe90292004-07-20 21:15:13 +00003761 int line, col;
3762 char *s;
Brian Paul45703642005-10-29 15:52:31 +00003763 fprintf(stderr, "program: %s\n", (char *) strz);
3764 fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
Brian Paula088f162006-09-05 23:08:51 +00003765 s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos,
3766 &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00003767 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
3768 } while (0)
3769#endif
Brian Paul5fe90292004-07-20 21:15:13 +00003770
Brian Paula088f162006-09-05 23:08:51 +00003771 _mesa_free(strz);
3772 _mesa_free(parsed);
3773
Jouk Jansen40322e12004-04-05 08:50:36 +00003774 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003775 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003776 }
3777
Jouk Jansen40322e12004-04-05 08:50:36 +00003778 grammar_destroy (arbprogram_syn_id);
3779
Brian Paul8c41a142005-11-19 15:36:28 +00003780 /*
3781 * Program string is syntactically correct at this point
3782 * Parse the tokenized version of the program now, generating
3783 * vertex/fragment program instructions.
3784 */
3785
Jouk Jansen40322e12004-04-05 08:50:36 +00003786 /* Initialize the arb_program struct */
3787 program->Base.String = strz;
Brian Paul383c39e2006-08-25 15:14:25 +00003788 program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
Jouk Jansen40322e12004-04-05 08:50:36 +00003789 program->Base.NumInstructions =
3790 program->Base.NumTemporaries =
3791 program->Base.NumParameters =
3792 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
Brian Paulde997602005-11-12 17:53:14 +00003793 program->Base.Parameters = _mesa_new_parameter_list ();
3794 program->Base.InputsRead = 0x0;
3795 program->Base.OutputsWritten = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003796 program->Position = 0;
3797 program->MajorVersion = program->MinorVersion = 0;
3798 program->PrecisionOption = GL_DONT_CARE;
3799 program->FogOption = GL_NONE;
3800 program->HintPositionInvariant = GL_FALSE;
3801 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
Brian Paul45cd2f92005-11-03 02:25:10 +00003802 program->TexturesUsed[a] = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003803 program->NumAluInstructions =
3804 program->NumTexInstructions =
3805 program->NumTexIndirections = 0;
Keith Whitwellc3626a92005-11-01 17:25:49 +00003806 program->UsesKill = 0;
3807
Jouk Jansen40322e12004-04-05 08:50:36 +00003808 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00003809 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003810
3811 /* Start examining the tokens in the array */
3812 inst = parsed;
3813
3814 /* Check the grammer rev */
3815 if (*inst++ != REVISION) {
Brian Paula088f162006-09-05 23:08:51 +00003816 program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00003817 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003818 }
3819 else {
Michal Krolb80bc052004-10-21 14:09:54 +00003820 /* ignore program target */
3821 inst++;
Brian Paul8c41a142005-11-19 15:36:28 +00003822 err = parse_instructions(ctx, inst, &vc_head, program);
Jouk Jansen40322e12004-04-05 08:50:36 +00003823 }
3824
3825 /*debug_variables(ctx, vc_head, program); */
3826
3827 /* We're done with the parsed binary array */
3828 var_cache_destroy (&vc_head);
3829
3830 _mesa_free (parsed);
Brian Paul45703642005-10-29 15:52:31 +00003831
Brian Paul8c41a142005-11-19 15:36:28 +00003832 /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
3833 * to size [ap.Base.NumInstructions].
3834 */
Brian Paula7543902006-08-24 21:58:32 +00003835 program->Base.Instructions
3836 = _mesa_realloc_instructions(program->Base.Instructions,
3837 MAX_INSTRUCTIONS,
3838 program->Base.NumInstructions);
3839
Brian Paul45703642005-10-29 15:52:31 +00003840 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00003841}
Brian Paul8c41a142005-11-19 15:36:28 +00003842
3843
3844
3845void
3846_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
3847 const GLvoid *str, GLsizei len,
Brian Paul122629f2006-07-20 16:49:57 +00003848 struct gl_fragment_program *program)
Brian Paul8c41a142005-11-19 15:36:28 +00003849{
3850 struct arb_program ap;
3851 GLuint i;
3852
3853 ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
Brian Paul95801792005-12-06 15:41:43 +00003854 if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
Brian Paul8c41a142005-11-19 15:36:28 +00003855 /* Error in the program. Just return. */
3856 return;
3857 }
3858
3859 /* Copy the relevant contents of the arb_program struct into the
3860 * fragment_program struct.
3861 */
3862 program->Base.String = ap.Base.String;
3863 program->Base.NumInstructions = ap.Base.NumInstructions;
3864 program->Base.NumTemporaries = ap.Base.NumTemporaries;
3865 program->Base.NumParameters = ap.Base.NumParameters;
3866 program->Base.NumAttributes = ap.Base.NumAttributes;
3867 program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
Roland Scheideggere6de1ed2006-08-30 11:55:18 +00003868 program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
3869 program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
3870 program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
3871 program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
3872 program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
Brian21f99792007-01-09 11:00:21 -07003873 program->Base.NumAluInstructions = ap.Base.NumAluInstructions;
3874 program->Base.NumTexInstructions = ap.Base.NumTexInstructions;
3875 program->Base.NumTexIndirections = ap.Base.NumTexIndirections;
3876 program->Base.NumNativeAluInstructions = ap.Base.NumAluInstructions;
3877 program->Base.NumNativeTexInstructions = ap.Base.NumTexInstructions;
3878 program->Base.NumNativeTexIndirections = ap.Base.NumTexIndirections;
Brian Paul8c41a142005-11-19 15:36:28 +00003879 program->Base.InputsRead = ap.Base.InputsRead;
3880 program->Base.OutputsWritten = ap.Base.OutputsWritten;
3881 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
Brianc9db2232007-01-04 17:22:19 -07003882 program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
Brian Paul8c41a142005-11-19 15:36:28 +00003883 program->FogOption = ap.FogOption;
Keith Whitwell7ecdfb22007-03-04 21:47:05 +00003884 program->UsesKill = ap.UsesKill;
Brian Paul8c41a142005-11-19 15:36:28 +00003885
3886 if (program->Base.Instructions)
3887 _mesa_free(program->Base.Instructions);
3888 program->Base.Instructions = ap.Base.Instructions;
3889
3890 if (program->Base.Parameters)
3891 _mesa_free_parameter_list(program->Base.Parameters);
3892 program->Base.Parameters = ap.Base.Parameters;
3893
3894#if DEBUG_FP
Brian Paul11a54c32006-11-15 19:54:25 +00003895 _mesa_printf("____________Fragment program %u ________\n", program->Base.ID);
3896 _mesa_print_program(&program->Base);
Brian Paul8c41a142005-11-19 15:36:28 +00003897#endif
3898}
3899
3900
3901
3902/**
3903 * Parse the vertex program string. If success, update the given
3904 * vertex_program object with the new program. Else, leave the vertex_program
3905 * object unchanged.
3906 */
3907void
3908_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
3909 const GLvoid *str, GLsizei len,
Brian Paul122629f2006-07-20 16:49:57 +00003910 struct gl_vertex_program *program)
Brian Paul8c41a142005-11-19 15:36:28 +00003911{
3912 struct arb_program ap;
3913
3914 ASSERT(target == GL_VERTEX_PROGRAM_ARB);
3915
Brian Paul95801792005-12-06 15:41:43 +00003916 if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
Brian Paul8c41a142005-11-19 15:36:28 +00003917 /* Error in the program. Just return. */
3918 return;
3919 }
3920
3921 /* Copy the relevant contents of the arb_program struct into the
3922 * vertex_program struct.
3923 */
3924 program->Base.String = ap.Base.String;
3925 program->Base.NumInstructions = ap.Base.NumInstructions;
3926 program->Base.NumTemporaries = ap.Base.NumTemporaries;
3927 program->Base.NumParameters = ap.Base.NumParameters;
3928 program->Base.NumAttributes = ap.Base.NumAttributes;
3929 program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
Roland Scheideggere6de1ed2006-08-30 11:55:18 +00003930 program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
3931 program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
3932 program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
3933 program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
3934 program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
Brian Paul8c41a142005-11-19 15:36:28 +00003935 program->Base.InputsRead = ap.Base.InputsRead;
3936 program->Base.OutputsWritten = ap.Base.OutputsWritten;
3937 program->IsPositionInvariant = ap.HintPositionInvariant;
3938
3939 if (program->Base.Instructions)
3940 _mesa_free(program->Base.Instructions);
3941 program->Base.Instructions = ap.Base.Instructions;
3942
3943 if (program->Base.Parameters)
3944 _mesa_free_parameter_list(program->Base.Parameters);
3945 program->Base.Parameters = ap.Base.Parameters;
3946
3947#if DEBUG_VP
Roland Scheidegger54dac2c2007-02-09 00:36:40 +01003948 _mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
Brian Paul8c41a142005-11-19 15:36:28 +00003949 _mesa_print_program(&program->Base);
3950#endif
3951}