blob: 5f039170c3b16ebdb88c5de74305643c92ce5feb [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
Brian Paul54cfe692005-10-21 15:22:36 +00003 * Version: 6.5
Jouk Jansen40322e12004-04-05 08:50:36 +00004 *
Brian Paul54cfe692005-10-21 15:22:36 +00005 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
Jouk Jansen40322e12004-04-05 08:50:36 +00006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#define DEBUG_PARSING 0
26
27/**
28 * \file arbprogparse.c
29 * ARB_*_program parser core
30 * \author Karl Rasche
31 */
32
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"
Brian Paul832026f2005-11-08 14:41:41 +000038#include "get.h"
Ian Romanick9bdfee32005-07-18 12:31:24 +000039
Alan Hourihane38b317d2004-12-14 09:11:52 +000040#ifndef __extension__
41#if !defined(__GNUC__) || (__GNUC__ < 2) || \
42 ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
Brian Paula6c423d2004-08-25 15:59:48 +000043# define __extension__
44#endif
Alan Hourihane38b317d2004-12-14 09:11:52 +000045#endif
Brian Paula6c423d2004-08-25 15:59:48 +000046
Jouk Jansen40322e12004-04-05 08:50:36 +000047/* TODO:
48 * Fragment Program Stuff:
49 * -----------------------------------------------------
50 *
51 * - things from Michal's email
52 * + overflow on atoi
53 * + not-overflowing floats (don't use parse_integer..)
54 * + can remove range checking in arbparse.c
55 *
56 * - check all limits of number of various variables
57 * + parameters
58 *
59 * - test! test! test!
60 *
61 * Vertex Program Stuff:
62 * -----------------------------------------------------
63 * - Optimize param array usage and count limits correctly, see spec,
64 * section 2.14.3.7
65 * + Record if an array is reference absolutly or relatively (or both)
66 * + For absolute arrays, store a bitmap of accesses
67 * + For single parameters, store an access flag
68 * + After parsing, make a parameter cleanup and merging pass, where
69 * relative arrays are layed out first, followed by abs arrays, and
70 * finally single state.
71 * + Remap offsets for param src and dst registers
72 * + Now we can properly count parameter usage
73 *
74 * - Multiple state binding errors in param arrays (see spec, just before
75 * section 2.14.3.3)
76 * - grep for XXX
77 *
78 * Mesa Stuff
79 * -----------------------------------------------------
80 * - User clipping planes vs. PositionInvariant
81 * - Is it sufficient to just multiply by the mvp to transform in the
82 * PositionInvariant case? Or do we need something more involved?
83 *
84 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
85 * - fetch state listed in program_parameters list
86 * + WTF should this go???
87 * + currently in nvvertexec.c and s_nvfragprog.c
88 *
89 * - allow for multiple address registers (and fetch address regs properly)
90 *
91 * Cosmetic Stuff
92 * -----------------------------------------------------
93 * - remove any leftover unused grammer.c stuff (dict_ ?)
94 * - fix grammer.c error handling so its not static
95 * - #ifdef around stuff pertaining to extentions
96 *
97 * Outstanding Questions:
98 * -----------------------------------------------------
99 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
100 * what gets hacked off because of this:
101 * + VERTEX_ATTRIB_MATRIXINDEX
102 * + VERTEX_ATTRIB_WEIGHT
103 * + MATRIX_MODELVIEW
104 * + MATRIX_PALETTE
105 *
106 * - When can we fetch env/local params from their own register files, and
107 * when to we have to fetch them into the main state register file?
108 * (think arrays)
109 *
110 * Grammar Changes:
111 * -----------------------------------------------------
112 */
113
114/* Changes since moving the file to shader directory
115
1162004-III-4 ------------------------------------------------------------
117- added #include "grammar_mesa.h"
118- removed grammar specific code part (it resides now in grammar.c)
119- added GL_ARB_fragment_program_shadow tokens
120- modified #include "arbparse_syn.h"
121- major changes inside _mesa_parse_arb_program()
122- check the program string for '\0' characters
123- copy the program string to a one-byte-longer location to have
124 it null-terminated
125- position invariance test (not writing to result.position) moved
126 to syntax part
127*/
128
129typedef GLubyte *production;
130
131/**
132 * This is the text describing the rules to parse the grammar
133 */
Brian Paula6c423d2004-08-25 15:59:48 +0000134__extension__ static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000135#include "arbprogram_syn.h"
136;
137
138/**
139 * These should match up with the values defined in arbprogram.syn
140 */
141
142/*
143 Changes:
144 - changed and merged V_* and F_* opcode values to OP_*.
145 - added GL_ARB_fragment_program_shadow specific tokens (michal)
146*/
Michal Krolb80bc052004-10-21 14:09:54 +0000147#define REVISION 0x09
Jouk Jansen40322e12004-04-05 08:50:36 +0000148
149/* program type */
150#define FRAGMENT_PROGRAM 0x01
151#define VERTEX_PROGRAM 0x02
152
153/* program section */
154#define OPTION 0x01
155#define INSTRUCTION 0x02
156#define DECLARATION 0x03
157#define END 0x04
158
Michal Krolb80bc052004-10-21 14:09:54 +0000159/* GL_ARB_fragment_program option */
160#define ARB_PRECISION_HINT_FASTEST 0x00
161#define ARB_PRECISION_HINT_NICEST 0x01
162#define ARB_FOG_EXP 0x02
163#define ARB_FOG_EXP2 0x03
164#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000165
Michal Krolb80bc052004-10-21 14:09:54 +0000166/* GL_ARB_vertex_program option */
167#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000168
Michal Krolb80bc052004-10-21 14:09:54 +0000169/* GL_ARB_fragment_program_shadow option */
170#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000171
Michal Krolb80bc052004-10-21 14:09:54 +0000172/* GL_ARB_draw_buffers option */
173#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000174
Jouk Jansen40322e12004-04-05 08:50:36 +0000175/* GL_ARB_fragment_program instruction class */
176#define OP_ALU_INST 0x00
177#define OP_TEX_INST 0x01
178
179/* GL_ARB_vertex_program instruction class */
180/* OP_ALU_INST */
181
182/* GL_ARB_fragment_program instruction type */
183#define OP_ALU_VECTOR 0x00
184#define OP_ALU_SCALAR 0x01
185#define OP_ALU_BINSC 0x02
186#define OP_ALU_BIN 0x03
187#define OP_ALU_TRI 0x04
188#define OP_ALU_SWZ 0x05
189#define OP_TEX_SAMPLE 0x06
190#define OP_TEX_KIL 0x07
191
192/* GL_ARB_vertex_program instruction type */
193#define OP_ALU_ARL 0x08
194/* OP_ALU_VECTOR */
195/* OP_ALU_SCALAR */
196/* OP_ALU_BINSC */
197/* OP_ALU_BIN */
198/* OP_ALU_TRI */
199/* OP_ALU_SWZ */
200
201/* GL_ARB_fragment_program instruction code */
202#define OP_ABS 0x00
203#define OP_ABS_SAT 0x1B
204#define OP_FLR 0x09
205#define OP_FLR_SAT 0x26
206#define OP_FRC 0x0A
207#define OP_FRC_SAT 0x27
208#define OP_LIT 0x0C
209#define OP_LIT_SAT 0x2A
210#define OP_MOV 0x11
211#define OP_MOV_SAT 0x30
212#define OP_COS 0x1F
213#define OP_COS_SAT 0x20
214#define OP_EX2 0x07
215#define OP_EX2_SAT 0x25
216#define OP_LG2 0x0B
217#define OP_LG2_SAT 0x29
218#define OP_RCP 0x14
219#define OP_RCP_SAT 0x33
220#define OP_RSQ 0x15
221#define OP_RSQ_SAT 0x34
222#define OP_SIN 0x38
223#define OP_SIN_SAT 0x39
224#define OP_SCS 0x35
225#define OP_SCS_SAT 0x36
226#define OP_POW 0x13
227#define OP_POW_SAT 0x32
228#define OP_ADD 0x01
229#define OP_ADD_SAT 0x1C
230#define OP_DP3 0x03
231#define OP_DP3_SAT 0x21
232#define OP_DP4 0x04
233#define OP_DP4_SAT 0x22
234#define OP_DPH 0x05
235#define OP_DPH_SAT 0x23
236#define OP_DST 0x06
237#define OP_DST_SAT 0x24
238#define OP_MAX 0x0F
239#define OP_MAX_SAT 0x2E
240#define OP_MIN 0x10
241#define OP_MIN_SAT 0x2F
242#define OP_MUL 0x12
243#define OP_MUL_SAT 0x31
244#define OP_SGE 0x16
245#define OP_SGE_SAT 0x37
246#define OP_SLT 0x17
247#define OP_SLT_SAT 0x3A
248#define OP_SUB 0x18
249#define OP_SUB_SAT 0x3B
250#define OP_XPD 0x1A
251#define OP_XPD_SAT 0x43
252#define OP_CMP 0x1D
253#define OP_CMP_SAT 0x1E
254#define OP_LRP 0x2B
255#define OP_LRP_SAT 0x2C
256#define OP_MAD 0x0E
257#define OP_MAD_SAT 0x2D
258#define OP_SWZ 0x19
259#define OP_SWZ_SAT 0x3C
260#define OP_TEX 0x3D
261#define OP_TEX_SAT 0x3E
262#define OP_TXB 0x3F
263#define OP_TXB_SAT 0x40
264#define OP_TXP 0x41
265#define OP_TXP_SAT 0x42
266#define OP_KIL 0x28
267
268/* GL_ARB_vertex_program instruction code */
269#define OP_ARL 0x02
270/* OP_ABS */
271/* OP_FLR */
272/* OP_FRC */
273/* OP_LIT */
274/* OP_MOV */
275/* OP_EX2 */
276#define OP_EXP 0x08
277/* OP_LG2 */
278#define OP_LOG 0x0D
279/* OP_RCP */
280/* OP_RSQ */
281/* OP_POW */
282/* OP_ADD */
283/* OP_DP3 */
284/* OP_DP4 */
285/* OP_DPH */
286/* OP_DST */
287/* OP_MAX */
288/* OP_MIN */
289/* OP_MUL */
290/* OP_SGE */
291/* OP_SLT */
292/* OP_SUB */
293/* OP_XPD */
294/* OP_MAD */
295/* OP_SWZ */
296
297/* fragment attribute binding */
298#define FRAGMENT_ATTRIB_COLOR 0x01
299#define FRAGMENT_ATTRIB_TEXCOORD 0x02
300#define FRAGMENT_ATTRIB_FOGCOORD 0x03
301#define FRAGMENT_ATTRIB_POSITION 0x04
302
303/* vertex attribute binding */
304#define VERTEX_ATTRIB_POSITION 0x01
305#define VERTEX_ATTRIB_WEIGHT 0x02
306#define VERTEX_ATTRIB_NORMAL 0x03
307#define VERTEX_ATTRIB_COLOR 0x04
308#define VERTEX_ATTRIB_FOGCOORD 0x05
309#define VERTEX_ATTRIB_TEXCOORD 0x06
310#define VERTEX_ATTRIB_MATRIXINDEX 0x07
311#define VERTEX_ATTRIB_GENERIC 0x08
312
313/* fragment result binding */
314#define FRAGMENT_RESULT_COLOR 0x01
315#define FRAGMENT_RESULT_DEPTH 0x02
316
317/* vertex result binding */
318#define VERTEX_RESULT_POSITION 0x01
319#define VERTEX_RESULT_COLOR 0x02
320#define VERTEX_RESULT_FOGCOORD 0x03
321#define VERTEX_RESULT_POINTSIZE 0x04
322#define VERTEX_RESULT_TEXCOORD 0x05
323
324/* texture target */
325#define TEXTARGET_1D 0x01
326#define TEXTARGET_2D 0x02
327#define TEXTARGET_3D 0x03
328#define TEXTARGET_RECT 0x04
329#define TEXTARGET_CUBE 0x05
330/* GL_ARB_fragment_program_shadow */
331#define TEXTARGET_SHADOW1D 0x06
332#define TEXTARGET_SHADOW2D 0x07
333#define TEXTARGET_SHADOWRECT 0x08
334
335/* face type */
336#define FACE_FRONT 0x00
337#define FACE_BACK 0x01
338
339/* color type */
340#define COLOR_PRIMARY 0x00
341#define COLOR_SECONDARY 0x01
342
343/* component */
344#define COMPONENT_X 0x00
345#define COMPONENT_Y 0x01
346#define COMPONENT_Z 0x02
347#define COMPONENT_W 0x03
348#define COMPONENT_0 0x04
349#define COMPONENT_1 0x05
350
351/* array index type */
352#define ARRAY_INDEX_ABSOLUTE 0x00
353#define ARRAY_INDEX_RELATIVE 0x01
354
355/* matrix name */
356#define MATRIX_MODELVIEW 0x01
357#define MATRIX_PROJECTION 0x02
358#define MATRIX_MVP 0x03
359#define MATRIX_TEXTURE 0x04
360#define MATRIX_PALETTE 0x05
361#define MATRIX_PROGRAM 0x06
362
363/* matrix modifier */
364#define MATRIX_MODIFIER_IDENTITY 0x00
365#define MATRIX_MODIFIER_INVERSE 0x01
366#define MATRIX_MODIFIER_TRANSPOSE 0x02
367#define MATRIX_MODIFIER_INVTRANS 0x03
368
369/* constant type */
370#define CONSTANT_SCALAR 0x01
371#define CONSTANT_VECTOR 0x02
372
373/* program param type */
374#define PROGRAM_PARAM_ENV 0x01
375#define PROGRAM_PARAM_LOCAL 0x02
376
377/* register type */
378#define REGISTER_ATTRIB 0x01
379#define REGISTER_PARAM 0x02
380#define REGISTER_RESULT 0x03
381#define REGISTER_ESTABLISHED_NAME 0x04
382
383/* param binding */
384#define PARAM_NULL 0x00
385#define PARAM_ARRAY_ELEMENT 0x01
386#define PARAM_STATE_ELEMENT 0x02
387#define PARAM_PROGRAM_ELEMENT 0x03
388#define PARAM_PROGRAM_ELEMENTS 0x04
389#define PARAM_CONSTANT 0x05
390
391/* param state property */
392#define STATE_MATERIAL_PARSER 0x01
393#define STATE_LIGHT_PARSER 0x02
394#define STATE_LIGHT_MODEL 0x03
395#define STATE_LIGHT_PROD 0x04
396#define STATE_FOG 0x05
397#define STATE_MATRIX_ROWS 0x06
398/* GL_ARB_fragment_program */
399#define STATE_TEX_ENV 0x07
400#define STATE_DEPTH 0x08
401/* GL_ARB_vertex_program */
402#define STATE_TEX_GEN 0x09
403#define STATE_CLIP_PLANE 0x0A
404#define STATE_POINT 0x0B
405
406/* state material property */
407#define MATERIAL_AMBIENT 0x01
408#define MATERIAL_DIFFUSE 0x02
409#define MATERIAL_SPECULAR 0x03
410#define MATERIAL_EMISSION 0x04
411#define MATERIAL_SHININESS 0x05
412
413/* state light property */
414#define LIGHT_AMBIENT 0x01
415#define LIGHT_DIFFUSE 0x02
416#define LIGHT_SPECULAR 0x03
417#define LIGHT_POSITION 0x04
418#define LIGHT_ATTENUATION 0x05
419#define LIGHT_HALF 0x06
420#define LIGHT_SPOT_DIRECTION 0x07
421
422/* state light model property */
423#define LIGHT_MODEL_AMBIENT 0x01
424#define LIGHT_MODEL_SCENECOLOR 0x02
425
426/* state light product property */
427#define LIGHT_PROD_AMBIENT 0x01
428#define LIGHT_PROD_DIFFUSE 0x02
429#define LIGHT_PROD_SPECULAR 0x03
430
431/* state texture environment property */
432#define TEX_ENV_COLOR 0x01
433
434/* state texture generation coord property */
435#define TEX_GEN_EYE 0x01
436#define TEX_GEN_OBJECT 0x02
437
438/* state fog property */
439#define FOG_COLOR 0x01
440#define FOG_PARAMS 0x02
441
442/* state depth property */
443#define DEPTH_RANGE 0x01
444
445/* state point parameters property */
446#define POINT_SIZE 0x01
447#define POINT_ATTENUATION 0x02
448
449/* declaration */
450#define ATTRIB 0x01
451#define PARAM 0x02
452#define TEMP 0x03
453#define OUTPUT 0x04
454#define ALIAS 0x05
455/* GL_ARB_vertex_program */
456#define ADDRESS 0x06
457
458/*-----------------------------------------------------------------------
459 * From here on down is the semantic checking portion
460 *
461 */
462
463/**
464 * Variable Table Handling functions
465 */
466typedef enum
467{
468 vt_none,
469 vt_address,
470 vt_attrib,
471 vt_param,
472 vt_temp,
473 vt_output,
474 vt_alias
475} var_type;
476
477
Brian Paul7aebaf32005-10-30 21:23:23 +0000478/**
479 * Setting an explicit field for each of the binding properties is a bit
480 * wasteful of space, but it should be much more clear when reading later on..
Jouk Jansen40322e12004-04-05 08:50:36 +0000481 */
482struct var_cache
483{
484 GLubyte *name;
485 var_type type;
486 GLuint address_binding; /* The index of the address register we should
487 * be using */
488 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
Jouk Jansen40322e12004-04-05 08:50:36 +0000489 GLuint attrib_is_generic; /* If the attrib was specified through a generic
490 * vertex attrib */
491 GLuint temp_binding; /* The index of the temp register we are to use */
Brian Paul7aebaf32005-10-30 21:23:23 +0000492 GLuint output_binding; /* Output/result register number */
Jouk Jansen40322e12004-04-05 08:50:36 +0000493 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
494 * that this is aliased to */
495 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
496 * PROGRAM_ENV_PARAM} */
497 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
498 * the tokens representing our bound state (or constants)
499 * start */
500 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
501 * we take up with our state tokens or constants. Note that
502 * this is _not_ the same as the number of param registers
503 * we eventually use */
504 struct var_cache *next;
505};
506
507static GLvoid
508var_cache_create (struct var_cache **va)
509{
510 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
511 if (*va) {
512 (**va).name = NULL;
513 (**va).type = vt_none;
514 (**va).attrib_binding = ~0;
515 (**va).attrib_is_generic = 0;
516 (**va).temp_binding = ~0;
517 (**va).output_binding = ~0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000518 (**va).param_binding_type = ~0;
519 (**va).param_binding_begin = ~0;
520 (**va).param_binding_length = ~0;
521 (**va).alias_binding = NULL;
522 (**va).next = NULL;
523 }
524}
525
526static GLvoid
527var_cache_destroy (struct var_cache **va)
528{
529 if (*va) {
530 var_cache_destroy (&(**va).next);
531 _mesa_free (*va);
532 *va = NULL;
533 }
534}
535
536static GLvoid
537var_cache_append (struct var_cache **va, struct var_cache *nv)
538{
539 if (*va)
540 var_cache_append (&(**va).next, nv);
541 else
542 *va = nv;
543}
544
545static struct var_cache *
546var_cache_find (struct var_cache *va, GLubyte * name)
547{
Brian Paul0a360cf2005-01-17 01:21:03 +0000548 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000549
550 while (va) {
Brian Paulaa206952005-09-16 18:14:24 +0000551 if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000552 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000553 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000554 return va;
555 }
556
557 va = va->next;
558 }
559
560 return NULL;
561}
562
563/**
564 * constructs an integer from 4 GLubytes in LE format
565 */
566static GLuint
567parse_position (GLubyte ** inst)
568{
569 GLuint value;
570
571 value = (GLuint) (*(*inst)++);
572 value += (GLuint) (*(*inst)++) * 0x100;
573 value += (GLuint) (*(*inst)++) * 0x10000;
574 value += (GLuint) (*(*inst)++) * 0x1000000;
575
576 return value;
577}
578
579/**
580 * This will, given a string, lookup the string as a variable name in the
581 * var cache. If the name is found, the var cache node corresponding to the
582 * var name is returned. If it is not found, a new entry is allocated
583 *
584 * \param I Points into the binary array where the string identifier begins
585 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
586 * \return The location on the var_cache corresponding the the string starting at I
587 */
588static struct var_cache *
589parse_string (GLubyte ** inst, struct var_cache **vc_head,
590 struct arb_program *Program, GLuint * found)
591{
592 GLubyte *i = *inst;
593 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000594 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000595
596 *inst += _mesa_strlen ((char *) i) + 1;
597
598 va = var_cache_find (*vc_head, i);
599
600 if (va) {
601 *found = 1;
602 return va;
603 }
604
605 *found = 0;
606 var_cache_create (&va);
607 va->name = i;
608
609 var_cache_append (vc_head, va);
610
611 return va;
612}
613
614static char *
615parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
616{
617 GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000618 (void) Program;
619
Jouk Jansen40322e12004-04-05 08:50:36 +0000620 *inst += _mesa_strlen ((char *) i) + 1;
621
622 return (char *) i;
623}
624
625/**
Brian Paul05908952004-06-08 15:20:23 +0000626 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000627 */
Brian Paul05908952004-06-08 15:20:23 +0000628static GLint
Jouk Jansen40322e12004-04-05 08:50:36 +0000629parse_sign (GLubyte ** inst)
630{
631 /*return *(*inst)++ != '+'; */
632
633 if (**inst == '-') {
634 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000635 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000636 }
637 else if (**inst == '+') {
638 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000639 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000640 }
641
Brian Paul05908952004-06-08 15:20:23 +0000642 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000643}
644
645/**
646 * parses and returns signed integer
647 */
648static GLint
649parse_integer (GLubyte ** inst, struct arb_program *Program)
650{
651 GLint sign;
652 GLint value;
653
654 /* check if *inst points to '+' or '-'
655 * if yes, grab the sign and increment *inst
656 */
657 sign = parse_sign (inst);
658
659 /* now check if *inst points to 0
660 * if yes, increment the *inst and return the default value
661 */
662 if (**inst == 0) {
663 (*inst)++;
664 return 0;
665 }
666
667 /* parse the integer as you normally would do it */
668 value = _mesa_atoi (parse_string_without_adding (inst, Program));
669
670 /* now, after terminating 0 there is a position
671 * to parse it - parse_position()
672 */
673 Program->Position = parse_position (inst);
674
Brian Paul05908952004-06-08 15:20:23 +0000675 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000676}
677
678/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000679 Accumulate this string of digits, and return them as
680 a large integer represented in floating point (for range).
681 If scale is not NULL, also accumulates a power-of-ten
682 integer scale factor that represents the number of digits
683 in the string.
684*/
685static GLdouble
686parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
687{
688 GLdouble value = 0.0;
689 GLdouble oscale = 1.0;
690
691 if (**inst == 0) { /* this string of digits is empty-- do nothing */
692 (*inst)++;
693 }
694 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000695 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000696 GLubyte digit = *((*inst)++);
697 value = value * 10.0 + (GLint) (digit - '0');
698 oscale *= 10.0;
699 }
700 assert(**inst == 0); /* integer string should end with 0 */
701 (*inst)++; /* skip over terminating 0 */
702 Program->Position = parse_position(inst); /* skip position (from integer) */
703 }
704 if (scale)
705 *scale = oscale;
706 return value;
707}
708
709/**
710 Parse an unsigned floating-point number from this stream of tokenized
711 characters. Example floating-point formats supported:
712 12.34
713 12
714 0.34
715 .34
716 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000717 */
718static GLfloat
719parse_float (GLubyte ** inst, struct arb_program *Program)
720{
Brian Paul1ff8f502005-02-16 15:08:29 +0000721 GLint exponent;
722 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000723
Brian Paul1ff8f502005-02-16 15:08:29 +0000724 whole = parse_float_string(inst, Program, 0);
725 fraction = parse_float_string(inst, Program, &fracScale);
726
727 /* Parse signed exponent */
728 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000729
Brian Paul1ff8f502005-02-16 15:08:29 +0000730 /* Assemble parts of floating-point number: */
731 return (GLfloat) ((whole + fraction / fracScale) *
732 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000733}
734
735
736/**
737 */
738static GLfloat
739parse_signed_float (GLubyte ** inst, struct arb_program *Program)
740{
Brian Paul05908952004-06-08 15:20:23 +0000741 GLint sign = parse_sign (inst);
742 GLfloat value = parse_float (inst, Program);
743 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000744}
745
746/**
747 * This picks out a constant value from the parsed array. The constant vector is r
748 * returned in the *values array, which should be of length 4.
749 *
750 * \param values - The 4 component vector with the constant value in it
751 */
752static GLvoid
753parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
754 GLboolean use)
755{
756 GLuint components, i;
757
758
759 switch (*(*inst)++) {
760 case CONSTANT_SCALAR:
761 if (use == GL_TRUE) {
762 values[0] =
763 values[1] =
764 values[2] = values[3] = parse_float (inst, Program);
765 }
766 else {
767 values[0] =
768 values[1] =
769 values[2] = values[3] = parse_signed_float (inst, Program);
770 }
771
772 break;
773 case CONSTANT_VECTOR:
774 values[0] = values[1] = values[2] = 0;
775 values[3] = 1;
776 components = *(*inst)++;
777 for (i = 0; i < components; i++) {
778 values[i] = parse_signed_float (inst, Program);
779 }
780 break;
781 }
782}
783
784/**
785 * \param offset The offset from the address register that we should
786 * address
787 *
788 * \return 0 on sucess, 1 on error
789 */
790static GLuint
791parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
792 GLint *offset)
793{
794 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000795 return 0;
796}
797
798/**
799 * \param color 0 if color type is primary, 1 if color type is secondary
800 * \return 0 on sucess, 1 on error
801 */
802static GLuint
803parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
804 GLint * color)
805{
Brian Paula6c423d2004-08-25 15:59:48 +0000806 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000807 *color = *(*inst)++ != COLOR_PRIMARY;
808 return 0;
809}
810
811/**
812 * Get an integer corresponding to a generic vertex attribute.
813 *
814 * \return 0 on sucess, 1 on error
815 */
816static GLuint
817parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
818 struct arb_program *Program, GLuint *attrib)
819{
Brian Paulbd997cd2004-07-20 21:12:56 +0000820 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000821
Brian Paulbd997cd2004-07-20 21:12:56 +0000822 if ((i < 0) || (i > MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000823 {
824 _mesa_set_program_error (ctx, Program->Position,
825 "Invalid generic vertex attribute index");
826 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
827
828 return 1;
829 }
830
Brian Paulbd997cd2004-07-20 21:12:56 +0000831 *attrib = (GLuint) i;
832
Jouk Jansen40322e12004-04-05 08:50:36 +0000833 return 0;
834}
835
836
837/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000838 * \param color The index of the color buffer to write into
839 * \return 0 on sucess, 1 on error
840 */
841static GLuint
842parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
843 struct arb_program *Program, GLuint * color)
844{
845 GLint i = parse_integer (inst, Program);
846
847 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
848 _mesa_set_program_error (ctx, Program->Position,
849 "Invalid draw buffer index");
850 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid draw buffer index");
851 return 1;
852 }
853
854 *color = (GLuint) i;
855 return 0;
856}
857
858
859/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000860 * \param coord The texture unit index
861 * \return 0 on sucess, 1 on error
862 */
863static GLuint
864parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
865 struct arb_program *Program, GLuint * coord)
866{
Brian Paulbd997cd2004-07-20 21:12:56 +0000867 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000868
Brian Paula6c423d2004-08-25 15:59:48 +0000869 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000870 _mesa_set_program_error (ctx, Program->Position,
871 "Invalid texture unit index");
872 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
873 return 1;
874 }
875
Brian Paulbd997cd2004-07-20 21:12:56 +0000876 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000877 return 0;
878}
879
880/**
881 * \param coord The weight index
882 * \return 0 on sucess, 1 on error
883 */
884static GLuint
885parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
886 GLint * coord)
887{
888 *coord = parse_integer (inst, Program);
889
890 if ((*coord < 0) || (*coord >= 1)) {
891 _mesa_set_program_error (ctx, Program->Position,
892 "Invalid weight index");
893 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
894 return 1;
895 }
896
897 return 0;
898}
899
900/**
901 * \param coord The clip plane index
902 * \return 0 on sucess, 1 on error
903 */
904static GLuint
905parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
906 struct arb_program *Program, GLint * coord)
907{
908 *coord = parse_integer (inst, Program);
909
910 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
911 _mesa_set_program_error (ctx, Program->Position,
912 "Invalid clip plane index");
913 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
914 return 1;
915 }
916
917 return 0;
918}
919
920
921/**
922 * \return 0 on front face, 1 on back face
923 */
924static GLuint
925parse_face_type (GLubyte ** inst)
926{
927 switch (*(*inst)++) {
928 case FACE_FRONT:
929 return 0;
930
931 case FACE_BACK:
932 return 1;
933 }
934 return 0;
935}
936
937
938/**
939 * Given a matrix and a modifier token on the binary array, return tokens
940 * that _mesa_fetch_state() [program.c] can understand.
941 *
942 * \param matrix - the matrix we are talking about
943 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
944 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
945 * \return 0 on sucess, 1 on failure
946 */
947static GLuint
948parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
949 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
950{
951 GLubyte mat = *(*inst)++;
952
953 *matrix_idx = 0;
954
955 switch (mat) {
956 case MATRIX_MODELVIEW:
957 *matrix = STATE_MODELVIEW;
958 *matrix_idx = parse_integer (inst, Program);
959 if (*matrix_idx > 0) {
960 _mesa_set_program_error (ctx, Program->Position,
961 "ARB_vertex_blend not supported\n");
962 _mesa_error (ctx, GL_INVALID_OPERATION,
963 "ARB_vertex_blend not supported\n");
964 return 1;
965 }
966 break;
967
968 case MATRIX_PROJECTION:
969 *matrix = STATE_PROJECTION;
970 break;
971
972 case MATRIX_MVP:
973 *matrix = STATE_MVP;
974 break;
975
976 case MATRIX_TEXTURE:
977 *matrix = STATE_TEXTURE;
978 *matrix_idx = parse_integer (inst, Program);
979 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
980 _mesa_set_program_error (ctx, Program->Position,
981 "Invalid Texture Unit");
982 _mesa_error (ctx, GL_INVALID_OPERATION,
983 "Invalid Texture Unit: %d", *matrix_idx);
984 return 1;
985 }
986 break;
987
988 /* This is not currently supported (ARB_matrix_palette) */
989 case MATRIX_PALETTE:
990 *matrix_idx = parse_integer (inst, Program);
991 _mesa_set_program_error (ctx, Program->Position,
992 "ARB_matrix_palette not supported\n");
993 _mesa_error (ctx, GL_INVALID_OPERATION,
994 "ARB_matrix_palette not supported\n");
995 return 1;
996 break;
997
998 case MATRIX_PROGRAM:
999 *matrix = STATE_PROGRAM;
1000 *matrix_idx = parse_integer (inst, Program);
1001 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
1002 _mesa_set_program_error (ctx, Program->Position,
1003 "Invalid Program Matrix");
1004 _mesa_error (ctx, GL_INVALID_OPERATION,
1005 "Invalid Program Matrix: %d", *matrix_idx);
1006 return 1;
1007 }
1008 break;
1009 }
1010
1011 switch (*(*inst)++) {
1012 case MATRIX_MODIFIER_IDENTITY:
1013 *matrix_modifier = 0;
1014 break;
1015 case MATRIX_MODIFIER_INVERSE:
1016 *matrix_modifier = STATE_MATRIX_INVERSE;
1017 break;
1018 case MATRIX_MODIFIER_TRANSPOSE:
1019 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1020 break;
1021 case MATRIX_MODIFIER_INVTRANS:
1022 *matrix_modifier = STATE_MATRIX_INVTRANS;
1023 break;
1024 }
1025
1026 return 0;
1027}
1028
1029
1030/**
1031 * This parses a state string (rather, the binary version of it) into
1032 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1033 *
1034 * \param inst - the start in the binary arry to start working from
1035 * \param state_tokens - the storage for the 6-token state description
1036 * \return - 0 on sucess, 1 on error
1037 */
1038static GLuint
1039parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
1040 struct arb_program *Program, GLint * state_tokens)
1041{
1042 switch (*(*inst)++) {
1043 case STATE_MATERIAL_PARSER:
1044 state_tokens[0] = STATE_MATERIAL;
1045 state_tokens[1] = parse_face_type (inst);
1046 switch (*(*inst)++) {
1047 case MATERIAL_AMBIENT:
1048 state_tokens[2] = STATE_AMBIENT;
1049 break;
1050 case MATERIAL_DIFFUSE:
1051 state_tokens[2] = STATE_DIFFUSE;
1052 break;
1053 case MATERIAL_SPECULAR:
1054 state_tokens[2] = STATE_SPECULAR;
1055 break;
1056 case MATERIAL_EMISSION:
1057 state_tokens[2] = STATE_EMISSION;
1058 break;
1059 case MATERIAL_SHININESS:
1060 state_tokens[2] = STATE_SHININESS;
1061 break;
1062 }
1063 break;
1064
1065 case STATE_LIGHT_PARSER:
1066 state_tokens[0] = STATE_LIGHT;
1067 state_tokens[1] = parse_integer (inst, Program);
1068
1069 /* Check the value of state_tokens[1] against the # of lights */
1070 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1071 _mesa_set_program_error (ctx, Program->Position,
1072 "Invalid Light Number");
1073 _mesa_error (ctx, GL_INVALID_OPERATION,
1074 "Invalid Light Number: %d", state_tokens[1]);
1075 return 1;
1076 }
1077
1078 switch (*(*inst)++) {
1079 case LIGHT_AMBIENT:
1080 state_tokens[2] = STATE_AMBIENT;
1081 break;
1082 case LIGHT_DIFFUSE:
1083 state_tokens[2] = STATE_DIFFUSE;
1084 break;
1085 case LIGHT_SPECULAR:
1086 state_tokens[2] = STATE_SPECULAR;
1087 break;
1088 case LIGHT_POSITION:
1089 state_tokens[2] = STATE_POSITION;
1090 break;
1091 case LIGHT_ATTENUATION:
1092 state_tokens[2] = STATE_ATTENUATION;
1093 break;
1094 case LIGHT_HALF:
1095 state_tokens[2] = STATE_HALF;
1096 break;
1097 case LIGHT_SPOT_DIRECTION:
1098 state_tokens[2] = STATE_SPOT_DIRECTION;
1099 break;
1100 }
1101 break;
1102
1103 case STATE_LIGHT_MODEL:
1104 switch (*(*inst)++) {
1105 case LIGHT_MODEL_AMBIENT:
1106 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1107 break;
1108 case LIGHT_MODEL_SCENECOLOR:
1109 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1110 state_tokens[1] = parse_face_type (inst);
1111 break;
1112 }
1113 break;
1114
1115 case STATE_LIGHT_PROD:
1116 state_tokens[0] = STATE_LIGHTPROD;
1117 state_tokens[1] = parse_integer (inst, Program);
1118
1119 /* Check the value of state_tokens[1] against the # of lights */
1120 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1121 _mesa_set_program_error (ctx, Program->Position,
1122 "Invalid Light Number");
1123 _mesa_error (ctx, GL_INVALID_OPERATION,
1124 "Invalid Light Number: %d", state_tokens[1]);
1125 return 1;
1126 }
1127
1128 state_tokens[2] = parse_face_type (inst);
1129 switch (*(*inst)++) {
1130 case LIGHT_PROD_AMBIENT:
1131 state_tokens[3] = STATE_AMBIENT;
1132 break;
1133 case LIGHT_PROD_DIFFUSE:
1134 state_tokens[3] = STATE_DIFFUSE;
1135 break;
1136 case LIGHT_PROD_SPECULAR:
1137 state_tokens[3] = STATE_SPECULAR;
1138 break;
1139 }
1140 break;
1141
1142
1143 case STATE_FOG:
1144 switch (*(*inst)++) {
1145 case FOG_COLOR:
1146 state_tokens[0] = STATE_FOG_COLOR;
1147 break;
1148 case FOG_PARAMS:
1149 state_tokens[0] = STATE_FOG_PARAMS;
1150 break;
1151 }
1152 break;
1153
1154 case STATE_TEX_ENV:
1155 state_tokens[1] = parse_integer (inst, Program);
1156 switch (*(*inst)++) {
1157 case TEX_ENV_COLOR:
1158 state_tokens[0] = STATE_TEXENV_COLOR;
1159 break;
1160 }
1161 break;
1162
1163 case STATE_TEX_GEN:
1164 {
1165 GLuint type, coord;
1166
1167 state_tokens[0] = STATE_TEXGEN;
1168 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1169
1170 if (parse_texcoord_num (ctx, inst, Program, &coord))
1171 return 1;
1172 state_tokens[1] = coord;
1173
1174 /* EYE or OBJECT */
1175 type = *(*inst++);
1176
1177 /* 0 - s, 1 - t, 2 - r, 3 - q */
1178 coord = *(*inst++);
1179
1180 if (type == TEX_GEN_EYE) {
1181 switch (coord) {
1182 case COMPONENT_X:
1183 state_tokens[2] = STATE_TEXGEN_EYE_S;
1184 break;
1185 case COMPONENT_Y:
1186 state_tokens[2] = STATE_TEXGEN_EYE_T;
1187 break;
1188 case COMPONENT_Z:
1189 state_tokens[2] = STATE_TEXGEN_EYE_R;
1190 break;
1191 case COMPONENT_W:
1192 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1193 break;
1194 }
1195 }
1196 else {
1197 switch (coord) {
1198 case COMPONENT_X:
1199 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1200 break;
1201 case COMPONENT_Y:
1202 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1203 break;
1204 case COMPONENT_Z:
1205 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1206 break;
1207 case COMPONENT_W:
1208 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1209 break;
1210 }
1211 }
1212 }
1213 break;
1214
1215 case STATE_DEPTH:
1216 switch (*(*inst)++) {
1217 case DEPTH_RANGE:
1218 state_tokens[0] = STATE_DEPTH_RANGE;
1219 break;
1220 }
1221 break;
1222
1223 case STATE_CLIP_PLANE:
1224 state_tokens[0] = STATE_CLIPPLANE;
1225 state_tokens[1] = parse_integer (inst, Program);
1226 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
1227 return 1;
1228 break;
1229
1230 case STATE_POINT:
1231 switch (*(*inst++)) {
1232 case POINT_SIZE:
1233 state_tokens[0] = STATE_POINT_SIZE;
1234 break;
1235
1236 case POINT_ATTENUATION:
1237 state_tokens[0] = STATE_POINT_ATTENUATION;
1238 break;
1239 }
1240 break;
1241
1242 /* XXX: I think this is the correct format for a matrix row */
1243 case STATE_MATRIX_ROWS:
1244 state_tokens[0] = STATE_MATRIX;
1245 if (parse_matrix
1246 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
1247 &state_tokens[5]))
1248 return 1;
1249
1250 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
1251
1252 if ((**inst) != 0) { /* Either the last row, 0 */
1253 state_tokens[4] = parse_integer (inst, Program);
1254 if (state_tokens[4] < state_tokens[3]) {
1255 _mesa_set_program_error (ctx, Program->Position,
1256 "Second matrix index less than the first");
1257 _mesa_error (ctx, GL_INVALID_OPERATION,
1258 "Second matrix index (%d) less than the first (%d)",
1259 state_tokens[4], state_tokens[3]);
1260 return 1;
1261 }
1262 }
1263 else {
1264 state_tokens[4] = state_tokens[3];
1265 (*inst)++;
1266 }
1267 break;
1268 }
1269
1270 return 0;
1271}
1272
1273/**
1274 * This parses a state string (rather, the binary version of it) into
1275 * a 6-token similar for the state fetching code in program.c
1276 *
1277 * One might ask, why fetch these parameters into just like you fetch
1278 * state when they are already stored in other places?
1279 *
1280 * Because of array offsets -> We can stick env/local parameters in the
1281 * middle of a parameter array and then index someplace into the array
1282 * when we execute.
1283 *
1284 * One optimization might be to only do this for the cases where the
1285 * env/local parameters end up inside of an array, and leave the
1286 * single parameters (or arrays of pure env/local pareameters) in their
1287 * respective register files.
1288 *
1289 * For ENV parameters, the format is:
1290 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1291 * state_tokens[1] = STATE_ENV
1292 * state_tokens[2] = the parameter index
1293 *
1294 * for LOCAL parameters, the format is:
1295 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1296 * state_tokens[1] = STATE_LOCAL
1297 * state_tokens[2] = the parameter index
1298 *
1299 * \param inst - the start in the binary arry to start working from
1300 * \param state_tokens - the storage for the 6-token state description
1301 * \return - 0 on sucess, 1 on failure
1302 */
1303static GLuint
1304parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
1305 struct arb_program *Program, GLint * state_tokens)
1306{
1307 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1308 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1309 else
1310 state_tokens[0] = STATE_VERTEX_PROGRAM;
1311
1312
1313 switch (*(*inst)++) {
1314 case PROGRAM_PARAM_ENV:
1315 state_tokens[1] = STATE_ENV;
1316 state_tokens[2] = parse_integer (inst, Program);
1317
1318 /* Check state_tokens[2] against the number of ENV parameters available */
1319 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001320 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001321 ||
1322 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001323 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001324 _mesa_set_program_error (ctx, Program->Position,
1325 "Invalid Program Env Parameter");
1326 _mesa_error (ctx, GL_INVALID_OPERATION,
1327 "Invalid Program Env Parameter: %d",
1328 state_tokens[2]);
1329 return 1;
1330 }
1331
1332 break;
1333
1334 case PROGRAM_PARAM_LOCAL:
1335 state_tokens[1] = STATE_LOCAL;
1336 state_tokens[2] = parse_integer (inst, Program);
1337
1338 /* Check state_tokens[2] against the number of LOCAL parameters available */
1339 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001340 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001341 ||
1342 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001343 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001344 _mesa_set_program_error (ctx, Program->Position,
1345 "Invalid Program Local Parameter");
1346 _mesa_error (ctx, GL_INVALID_OPERATION,
1347 "Invalid Program Local Parameter: %d",
1348 state_tokens[2]);
1349 return 1;
1350 }
1351 break;
1352 }
1353
1354 return 0;
1355}
1356
1357/**
1358 * For ARB_vertex_program, programs are not allowed to use both an explicit
1359 * vertex attribute and a generic vertex attribute corresponding to the same
1360 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1361 *
1362 * This will walk our var_cache and make sure that nobody does anything fishy.
1363 *
1364 * \return 0 on sucess, 1 on error
1365 */
1366static GLuint
1367generic_attrib_check(struct var_cache *vc_head)
1368{
1369 int a;
1370 struct var_cache *curr;
1371 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1372 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1373
1374 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1375 explicitAttrib[a] = GL_FALSE;
1376 genericAttrib[a] = GL_FALSE;
1377 }
1378
1379 curr = vc_head;
1380 while (curr) {
1381 if (curr->type == vt_attrib) {
1382 if (curr->attrib_is_generic)
Brian Paul18e7c5c2005-10-30 21:46:00 +00001383 genericAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001384 else
Brian Paul18e7c5c2005-10-30 21:46:00 +00001385 explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001386 }
1387
1388 curr = curr->next;
1389 }
1390
1391 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1392 if ((explicitAttrib[a]) && (genericAttrib[a]))
1393 return 1;
1394 }
1395
1396 return 0;
1397}
1398
1399/**
1400 * This will handle the binding side of an ATTRIB var declaration
1401 *
Brian Paul18e7c5c2005-10-30 21:46:00 +00001402 * \param inputReg returns the input register index, one of the
1403 * VERT_ATTRIB_* or FRAG_ATTRIB_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001404 * \return returns 0 on sucess, 1 on error
Jouk Jansen40322e12004-04-05 08:50:36 +00001405 */
1406static GLuint
Brian Paul18e7c5c2005-10-30 21:46:00 +00001407parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
1408 struct arb_program *Program,
1409 GLuint *inputReg, GLuint *is_generic)
Jouk Jansen40322e12004-04-05 08:50:36 +00001410{
Jouk Jansen40322e12004-04-05 08:50:36 +00001411 GLint err = 0;
1412
1413 *is_generic = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001414
Jouk Jansen40322e12004-04-05 08:50:36 +00001415 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1416 switch (*(*inst)++) {
1417 case FRAGMENT_ATTRIB_COLOR:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001418 {
1419 GLint coord;
1420 err = parse_color_type (ctx, inst, Program, &coord);
1421 *inputReg = FRAG_ATTRIB_COL0 + coord;
1422 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001423 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001424 case FRAGMENT_ATTRIB_TEXCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001425 {
1426 GLuint texcoord;
1427 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1428 *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
1429 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001430 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001431 case FRAGMENT_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001432 *inputReg = FRAG_ATTRIB_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001433 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001434 case FRAGMENT_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001435 *inputReg = FRAG_ATTRIB_WPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001436 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001437 default:
1438 err = 1;
1439 break;
1440 }
1441 }
1442 else {
1443 switch (*(*inst)++) {
1444 case VERTEX_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001445 *inputReg = VERT_ATTRIB_POS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001446 break;
1447
1448 case VERTEX_ATTRIB_WEIGHT:
1449 {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001450 const char *msg = "ARB_vertex_blend not supported";
Jouk Jansen40322e12004-04-05 08:50:36 +00001451 GLint weight;
Jouk Jansen40322e12004-04-05 08:50:36 +00001452 err = parse_weight_num (ctx, inst, Program, &weight);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001453 *inputReg = VERT_ATTRIB_WEIGHT;
1454 _mesa_set_program_error(ctx, Program->Position, msg);
1455 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001456 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001457 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001458
1459 case VERTEX_ATTRIB_NORMAL:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001460 *inputReg = VERT_ATTRIB_NORMAL;
Jouk Jansen40322e12004-04-05 08:50:36 +00001461 break;
1462
1463 case VERTEX_ATTRIB_COLOR:
1464 {
1465 GLint color;
Jouk Jansen40322e12004-04-05 08:50:36 +00001466 err = parse_color_type (ctx, inst, Program, &color);
1467 if (color) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001468 *inputReg = VERT_ATTRIB_COLOR1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001469 }
1470 else {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001471 *inputReg = VERT_ATTRIB_COLOR0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001472 }
1473 }
1474 break;
1475
1476 case VERTEX_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001477 *inputReg = VERT_ATTRIB_FOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00001478 break;
1479
1480 case VERTEX_ATTRIB_TEXCOORD:
1481 {
1482 GLuint unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001483 err = parse_texcoord_num (ctx, inst, Program, &unit);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001484 *inputReg = VERT_ATTRIB_TEX0 + unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001485 }
1486 break;
1487
Jouk Jansen40322e12004-04-05 08:50:36 +00001488 case VERTEX_ATTRIB_MATRIXINDEX:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001489 /* Not supported at this time */
1490 {
1491 const char *msg = "ARB_palette_matrix not supported";
1492 parse_integer (inst, Program);
1493 _mesa_set_program_error (ctx, Program->Position, msg);
1494 _mesa_error (ctx, GL_INVALID_OPERATION, msg);
1495 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001496 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001497
1498 case VERTEX_ATTRIB_GENERIC:
1499 {
1500 GLuint attrib;
Jouk Jansen40322e12004-04-05 08:50:36 +00001501 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
1502 *is_generic = 1;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001503 *inputReg = attrib;
Jouk Jansen40322e12004-04-05 08:50:36 +00001504 }
1505 }
1506 break;
1507
1508 default:
1509 err = 1;
1510 break;
1511 }
1512 }
1513
1514 /* Can this even happen? */
1515 if (err) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001516 const char *msg = "Bad attribute binding";
1517 _mesa_set_program_error(ctx, Program->Position, msg);
1518 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001519 }
1520
Brian Paul18e7c5c2005-10-30 21:46:00 +00001521 Program->InputsRead |= (1 << *inputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001522
1523 return err;
1524}
1525
Brian Paul7aebaf32005-10-30 21:23:23 +00001526
Jouk Jansen40322e12004-04-05 08:50:36 +00001527/**
1528 * This translates between a binary token for an output variable type
1529 * and the mesa token for the same thing.
1530 *
Brian Paul7aebaf32005-10-30 21:23:23 +00001531 * \param inst The parsed tokens
1532 * \param outputReg Returned index/number of the output register,
Brian Paul90ebb582005-11-02 18:06:12 +00001533 * one of the VERT_RESULT_* or FRAG_RESULT_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001534 */
1535static GLuint
Brian Paul7aebaf32005-10-30 21:23:23 +00001536parse_result_binding(GLcontext *ctx, GLubyte **inst,
1537 GLuint *outputReg, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00001538{
Brian Paul7aebaf32005-10-30 21:23:23 +00001539 const GLubyte token = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001540
Brian Paul7aebaf32005-10-30 21:23:23 +00001541 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001542 case FRAGMENT_RESULT_COLOR:
Jouk Jansen40322e12004-04-05 08:50:36 +00001543 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001544 GLuint out_color;
1545
Brian Paulbe76b7f2004-10-04 14:40:05 +00001546 /* This gets result of the color buffer we're supposed to
Brian Paul7aebaf32005-10-30 21:23:23 +00001547 * draw into. This pertains to GL_ARB_draw_buffers.
Brian Paulbe76b7f2004-10-04 14:40:05 +00001548 */
1549 parse_output_color_num(ctx, inst, Program, &out_color);
Brian Paul7aebaf32005-10-30 21:23:23 +00001550 ASSERT(out_color < MAX_DRAW_BUFFERS);
Brian Paul90ebb582005-11-02 18:06:12 +00001551 *outputReg = FRAG_RESULT_COLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001552 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001553 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001554 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1555 *outputReg = VERT_RESULT_HPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001556 }
1557 break;
1558
1559 case FRAGMENT_RESULT_DEPTH:
Jouk Jansen40322e12004-04-05 08:50:36 +00001560 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001561 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
Brian Paul90ebb582005-11-02 18:06:12 +00001562 *outputReg = FRAG_RESULT_DEPR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001563 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001564 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001565 /* for vtx programs, this is VERTEX_RESULT_COLOR */
Jouk Jansen40322e12004-04-05 08:50:36 +00001566 GLint color_type;
1567 GLuint face_type = parse_face_type(inst);
Brian Paul7aebaf32005-10-30 21:23:23 +00001568 GLint err = parse_color_type(ctx, inst, Program, &color_type);
1569 if (err)
1570 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001571
Jouk Jansen40322e12004-04-05 08:50:36 +00001572 if (face_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001573 /* back face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001574 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001575 *outputReg = VERT_RESULT_BFC1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001576 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001577 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001578 *outputReg = VERT_RESULT_BFC0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001579 }
1580 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001581 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001582 /* front face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001583 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001584 *outputReg = VERT_RESULT_COL1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001585 }
1586 /* primary color */
1587 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001588 *outputReg = VERT_RESULT_COL0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001589 }
1590 }
1591 }
1592 break;
1593
1594 case VERTEX_RESULT_FOGCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001595 *outputReg = VERT_RESULT_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001596 break;
1597
1598 case VERTEX_RESULT_POINTSIZE:
Brian Paul7aebaf32005-10-30 21:23:23 +00001599 *outputReg = VERT_RESULT_PSIZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00001600 break;
1601
1602 case VERTEX_RESULT_TEXCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001603 {
1604 GLuint unit;
1605 if (parse_texcoord_num (ctx, inst, Program, &unit))
1606 return 1;
1607 *outputReg = VERT_RESULT_TEX0 + unit;
1608 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001609 break;
1610 }
1611
Brian Paul7aebaf32005-10-30 21:23:23 +00001612 Program->OutputsWritten |= (1 << *outputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001613
1614 return 0;
1615}
1616
Brian Paul7aebaf32005-10-30 21:23:23 +00001617
Jouk Jansen40322e12004-04-05 08:50:36 +00001618/**
1619 * This handles the declaration of ATTRIB variables
1620 *
1621 * XXX: Still needs
1622 * parse_vert_attrib_binding(), or something like that
1623 *
1624 * \return 0 on sucess, 1 on error
1625 */
1626static GLint
1627parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1628 struct arb_program *Program)
1629{
1630 GLuint found;
1631 char *error_msg;
1632 struct var_cache *attrib_var;
1633
1634 attrib_var = parse_string (inst, vc_head, Program, &found);
1635 Program->Position = parse_position (inst);
1636 if (found) {
1637 error_msg = (char *)
1638 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1639 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1640 attrib_var->name);
1641
1642 _mesa_set_program_error (ctx, Program->Position, error_msg);
1643 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1644
1645 _mesa_free (error_msg);
1646 return 1;
1647 }
1648
1649 attrib_var->type = vt_attrib;
1650
Brian Paul7aebaf32005-10-30 21:23:23 +00001651 if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
Brian Paul7aebaf32005-10-30 21:23:23 +00001652 &attrib_var->attrib_is_generic))
1653 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001654
Brian Paul7aebaf32005-10-30 21:23:23 +00001655 if (generic_attrib_check(*vc_head)) {
1656 _mesa_set_program_error(ctx, Program->Position,
1657 "Cannot use both a generic vertex attribute "
1658 "and a specific attribute of the same type");
1659 _mesa_error(ctx, GL_INVALID_OPERATION,
1660 "Cannot use both a generic vertex attribute and a specific "
1661 "attribute of the same type");
1662 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001663 }
1664
1665 Program->Base.NumAttributes++;
1666 return 0;
1667}
1668
1669/**
1670 * \param use -- TRUE if we're called when declaring implicit parameters,
1671 * FALSE if we're declaraing variables. This has to do with
1672 * if we get a signed or unsigned float for scalar constants
1673 */
1674static GLuint
1675parse_param_elements (GLcontext * ctx, GLubyte ** inst,
1676 struct var_cache *param_var,
1677 struct arb_program *Program, GLboolean use)
1678{
1679 GLint idx;
Brian Paul7aebaf32005-10-30 21:23:23 +00001680 GLuint err = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001681 GLint state_tokens[6];
1682 GLfloat const_values[4];
1683
Jouk Jansen40322e12004-04-05 08:50:36 +00001684 switch (*(*inst)++) {
1685 case PARAM_STATE_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001686 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1687 return 1;
1688
1689 /* If we adding STATE_MATRIX that has multiple rows, we need to
1690 * unroll it and call _mesa_add_state_reference() for each row
1691 */
1692 if ((state_tokens[0] == STATE_MATRIX)
1693 && (state_tokens[3] != state_tokens[4])) {
1694 GLint row;
1695 GLint first_row = state_tokens[3];
1696 GLint last_row = state_tokens[4];
1697
1698 for (row = first_row; row <= last_row; row++) {
1699 state_tokens[3] = state_tokens[4] = row;
1700
1701 idx =
1702 _mesa_add_state_reference (Program->Parameters,
1703 state_tokens);
1704 if (param_var->param_binding_begin == ~0U)
1705 param_var->param_binding_begin = idx;
1706 param_var->param_binding_length++;
1707 Program->Base.NumParameters++;
1708 }
1709 }
1710 else {
1711 idx =
1712 _mesa_add_state_reference (Program->Parameters, state_tokens);
1713 if (param_var->param_binding_begin == ~0U)
1714 param_var->param_binding_begin = idx;
1715 param_var->param_binding_length++;
1716 Program->Base.NumParameters++;
1717 }
1718 break;
1719
1720 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001721 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1722 return 1;
1723 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
1724 if (param_var->param_binding_begin == ~0U)
1725 param_var->param_binding_begin = idx;
1726 param_var->param_binding_length++;
1727 Program->Base.NumParameters++;
1728
1729 /* Check if there is more: 0 -> we're done, else its an integer */
1730 if (**inst) {
1731 GLuint out_of_range, new_idx;
1732 GLuint start_idx = state_tokens[2] + 1;
1733 GLuint end_idx = parse_integer (inst, Program);
1734
1735 out_of_range = 0;
1736 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1737 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001738 && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001739 || ((state_tokens[1] == STATE_LOCAL)
1740 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001741 ctx->Const.FragmentProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001742 out_of_range = 1;
1743 }
1744 else {
1745 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001746 && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001747 || ((state_tokens[1] == STATE_LOCAL)
1748 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001749 ctx->Const.VertexProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001750 out_of_range = 1;
1751 }
1752 if (out_of_range) {
1753 _mesa_set_program_error (ctx, Program->Position,
1754 "Invalid Program Parameter");
1755 _mesa_error (ctx, GL_INVALID_OPERATION,
1756 "Invalid Program Parameter: %d", end_idx);
1757 return 1;
1758 }
1759
1760 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1761 state_tokens[2] = new_idx;
1762 idx =
1763 _mesa_add_state_reference (Program->Parameters,
1764 state_tokens);
1765 param_var->param_binding_length++;
1766 Program->Base.NumParameters++;
1767 }
1768 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001769 else {
1770 (*inst)++;
1771 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001772 break;
1773
1774 case PARAM_CONSTANT:
1775 parse_constant (inst, const_values, Program, use);
1776 idx =
1777 _mesa_add_named_constant (Program->Parameters,
1778 (char *) param_var->name, const_values);
1779 if (param_var->param_binding_begin == ~0U)
1780 param_var->param_binding_begin = idx;
1781 param_var->param_binding_length++;
1782 Program->Base.NumParameters++;
1783 break;
1784
1785 default:
Brian Paul7aebaf32005-10-30 21:23:23 +00001786 _mesa_set_program_error(ctx, Program->Position,
1787 "Unexpected token in parse_param_elements()");
1788 _mesa_error(ctx, GL_INVALID_OPERATION,
1789 "Unexpected token in parse_param_elements()");
Jouk Jansen40322e12004-04-05 08:50:36 +00001790 return 1;
1791 }
1792
1793 /* Make sure we haven't blown past our parameter limits */
1794 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1795 (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001796 ctx->Const.VertexProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001797 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1798 && (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001799 ctx->Const.FragmentProgram.MaxLocalParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001800 _mesa_set_program_error (ctx, Program->Position,
1801 "Too many parameter variables");
1802 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1803 return 1;
1804 }
1805
1806 return err;
1807}
1808
Brian Paul7aebaf32005-10-30 21:23:23 +00001809
Jouk Jansen40322e12004-04-05 08:50:36 +00001810/**
1811 * This picks out PARAM program parameter bindings.
1812 *
1813 * XXX: This needs to be stressed & tested
1814 *
1815 * \return 0 on sucess, 1 on error
1816 */
1817static GLuint
1818parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1819 struct arb_program *Program)
1820{
Brian Paulbd997cd2004-07-20 21:12:56 +00001821 GLuint found, err;
1822 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001823 struct var_cache *param_var;
1824
1825 err = 0;
1826 param_var = parse_string (inst, vc_head, Program, &found);
1827 Program->Position = parse_position (inst);
1828
1829 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001830 char *error_msg = (char *)
1831 _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
Jouk Jansen40322e12004-04-05 08:50:36 +00001832 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1833 param_var->name);
1834
1835 _mesa_set_program_error (ctx, Program->Position, error_msg);
1836 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1837
1838 _mesa_free (error_msg);
1839 return 1;
1840 }
1841
1842 specified_length = parse_integer (inst, Program);
1843
1844 if (specified_length < 0) {
1845 _mesa_set_program_error (ctx, Program->Position,
1846 "Negative parameter array length");
1847 _mesa_error (ctx, GL_INVALID_OPERATION,
1848 "Negative parameter array length: %d", specified_length);
1849 return 1;
1850 }
1851
1852 param_var->type = vt_param;
1853 param_var->param_binding_length = 0;
1854
1855 /* Right now, everything is shoved into the main state register file.
1856 *
1857 * In the future, it would be nice to leave things ENV/LOCAL params
1858 * in their respective register files, if possible
1859 */
1860 param_var->param_binding_type = PROGRAM_STATE_VAR;
1861
1862 /* Remember to:
1863 * * - add each guy to the parameter list
1864 * * - increment the param_var->param_binding_len
1865 * * - store the param_var->param_binding_begin for the first one
1866 * * - compare the actual len to the specified len at the end
1867 */
1868 while (**inst != PARAM_NULL) {
1869 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1870 return 1;
1871 }
1872
1873 /* Test array length here! */
1874 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001875 if (specified_length != (int)param_var->param_binding_length) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001876 const char *msg
1877 = "Declared parameter array length does not match parameter list";
1878 _mesa_set_program_error(ctx, Program->Position, msg);
1879 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001880 }
1881 }
1882
1883 (*inst)++;
1884
1885 return 0;
1886}
1887
1888/**
1889 *
1890 */
1891static GLuint
1892parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1893 struct arb_program *Program, struct var_cache **new_var)
1894{
1895 struct var_cache *param_var;
1896
1897 /* First, insert a dummy entry into the var_cache */
1898 var_cache_create (&param_var);
1899 param_var->name = (GLubyte *) _mesa_strdup (" ");
1900 param_var->type = vt_param;
1901
1902 param_var->param_binding_length = 0;
1903 /* Don't fill in binding_begin; We use the default value of -1
1904 * to tell if its already initialized, elsewhere.
1905 *
1906 * param_var->param_binding_begin = 0;
1907 */
1908 param_var->param_binding_type = PROGRAM_STATE_VAR;
1909
1910 var_cache_append (vc_head, param_var);
1911
1912 /* Then fill it with juicy parameter goodness */
1913 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1914 return 1;
1915
1916 *new_var = param_var;
1917
1918 return 0;
1919}
1920
1921
1922/**
1923 * This handles the declaration of TEMP variables
1924 *
1925 * \return 0 on sucess, 1 on error
1926 */
1927static GLuint
1928parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1929 struct arb_program *Program)
1930{
1931 GLuint found;
1932 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00001933
1934 while (**inst != 0) {
1935 temp_var = parse_string (inst, vc_head, Program, &found);
1936 Program->Position = parse_position (inst);
1937 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001938 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001939 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
1940 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1941 temp_var->name);
1942
1943 _mesa_set_program_error (ctx, Program->Position, error_msg);
1944 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1945
1946 _mesa_free (error_msg);
1947 return 1;
1948 }
1949
1950 temp_var->type = vt_temp;
1951
1952 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1953 (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001954 ctx->Const.FragmentProgram.MaxTemps))
Jouk Jansen40322e12004-04-05 08:50:36 +00001955 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
1956 && (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001957 ctx->Const.VertexProgram.MaxTemps))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001958 _mesa_set_program_error (ctx, Program->Position,
1959 "Too many TEMP variables declared");
1960 _mesa_error (ctx, GL_INVALID_OPERATION,
1961 "Too many TEMP variables declared");
1962 return 1;
1963 }
1964
1965 temp_var->temp_binding = Program->Base.NumTemporaries;
1966 Program->Base.NumTemporaries++;
1967 }
1968 (*inst)++;
1969
1970 return 0;
1971}
1972
1973/**
1974 * This handles variables of the OUTPUT variety
1975 *
1976 * \return 0 on sucess, 1 on error
1977 */
1978static GLuint
1979parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1980 struct arb_program *Program)
1981{
1982 GLuint found;
1983 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00001984 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00001985
1986 output_var = parse_string (inst, vc_head, Program, &found);
1987 Program->Position = parse_position (inst);
1988 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001989 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001990 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
1991 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1992 output_var->name);
1993
1994 _mesa_set_program_error (ctx, Program->Position, error_msg);
1995 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1996
1997 _mesa_free (error_msg);
1998 return 1;
1999 }
2000
2001 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002002
2003 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2004 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002005}
2006
2007/**
2008 * This handles variables of the ALIAS kind
2009 *
2010 * \return 0 on sucess, 1 on error
2011 */
2012static GLuint
2013parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2014 struct arb_program *Program)
2015{
2016 GLuint found;
2017 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002018
2019 temp_var = parse_string (inst, vc_head, Program, &found);
2020 Program->Position = parse_position (inst);
2021
2022 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002023 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002024 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2025 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2026 temp_var->name);
2027
2028 _mesa_set_program_error (ctx, Program->Position, error_msg);
2029 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2030
2031 _mesa_free (error_msg);
2032 return 1;
2033 }
2034
2035 temp_var->type = vt_alias;
2036 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2037 Program->Position = parse_position (inst);
2038
2039 if (!found)
2040 {
Brian Paul7aebaf32005-10-30 21:23:23 +00002041 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002042 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2043 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2044 temp_var->alias_binding->name);
2045
2046 _mesa_set_program_error (ctx, Program->Position, error_msg);
2047 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2048
2049 _mesa_free (error_msg);
2050 return 1;
2051 }
2052
2053 return 0;
2054}
2055
2056/**
2057 * This handles variables of the ADDRESS kind
2058 *
2059 * \return 0 on sucess, 1 on error
2060 */
2061static GLuint
2062parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2063 struct arb_program *Program)
2064{
2065 GLuint found;
2066 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002067
2068 while (**inst != 0) {
2069 temp_var = parse_string (inst, vc_head, Program, &found);
2070 Program->Position = parse_position (inst);
2071 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002072 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002073 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2074 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2075 temp_var->name);
2076
2077 _mesa_set_program_error (ctx, Program->Position, error_msg);
2078 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2079
2080 _mesa_free (error_msg);
2081 return 1;
2082 }
2083
2084 temp_var->type = vt_address;
2085
2086 if (Program->Base.NumAddressRegs >=
Brian Paul05051032005-11-01 04:36:33 +00002087 ctx->Const.VertexProgram.MaxAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002088 const char *msg = "Too many ADDRESS variables declared";
2089 _mesa_set_program_error(ctx, Program->Position, msg);
2090
2091 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002092 return 1;
2093 }
2094
2095 temp_var->address_binding = Program->Base.NumAddressRegs;
2096 Program->Base.NumAddressRegs++;
2097 }
2098 (*inst)++;
2099
2100 return 0;
2101}
2102
2103/**
2104 * Parse a program declaration
2105 *
2106 * \return 0 on sucess, 1 on error
2107 */
2108static GLint
2109parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2110 struct arb_program *Program)
2111{
2112 GLint err = 0;
2113
2114 switch (*(*inst)++) {
2115 case ADDRESS:
2116 err = parse_address (ctx, inst, vc_head, Program);
2117 break;
2118
2119 case ALIAS:
2120 err = parse_alias (ctx, inst, vc_head, Program);
2121 break;
2122
2123 case ATTRIB:
2124 err = parse_attrib (ctx, inst, vc_head, Program);
2125 break;
2126
2127 case OUTPUT:
2128 err = parse_output (ctx, inst, vc_head, Program);
2129 break;
2130
2131 case PARAM:
2132 err = parse_param (ctx, inst, vc_head, Program);
2133 break;
2134
2135 case TEMP:
2136 err = parse_temp (ctx, inst, vc_head, Program);
2137 break;
2138 }
2139
2140 return err;
2141}
2142
2143/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002144 * Handle the parsing out of a masked destination register, either for a
2145 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002146 *
2147 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002148 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002149 * position invariant
2150 *
2151 * \param File - The register file we write to
2152 * \param Index - The register index we write to
2153 * \param WriteMask - The mask controlling which components we write (1->write)
2154 *
2155 * \return 0 on sucess, 1 on error
2156 */
2157static GLuint
2158parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2159 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002160 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002161{
Brian Paul7aebaf32005-10-30 21:23:23 +00002162 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002163 struct var_cache *dst;
2164
2165 /* We either have a result register specified, or a
2166 * variable that may or may not be writable
2167 */
2168 switch (*(*inst)++) {
2169 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002170 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002171 return 1;
2172 *File = PROGRAM_OUTPUT;
2173 break;
2174
2175 case REGISTER_ESTABLISHED_NAME:
2176 dst = parse_string (inst, vc_head, Program, &result);
2177 Program->Position = parse_position (inst);
2178
2179 /* If the name has never been added to our symbol table, we're hosed */
2180 if (!result) {
2181 _mesa_set_program_error (ctx, Program->Position,
2182 "0: Undefined variable");
2183 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2184 dst->name);
2185 return 1;
2186 }
2187
2188 switch (dst->type) {
2189 case vt_output:
2190 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002191 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002192 break;
2193
2194 case vt_temp:
2195 *File = PROGRAM_TEMPORARY;
2196 *Index = dst->temp_binding;
2197 break;
2198
2199 /* If the var type is not vt_output or vt_temp, no go */
2200 default:
2201 _mesa_set_program_error (ctx, Program->Position,
2202 "Destination register is read only");
2203 _mesa_error (ctx, GL_INVALID_OPERATION,
2204 "Destination register is read only: %s",
2205 dst->name);
2206 return 1;
2207 }
2208 break;
2209
2210 default:
2211 _mesa_set_program_error (ctx, Program->Position,
2212 "Unexpected opcode in parse_masked_dst_reg()");
2213 _mesa_error (ctx, GL_INVALID_OPERATION,
2214 "Unexpected opcode in parse_masked_dst_reg()");
2215 return 1;
2216 }
2217
2218
2219 /* Position invariance test */
2220 /* This test is done now in syntax portion - when position invariance OPTION
2221 is specified, "result.position" rule is disabled so there is no way
2222 to write the position
2223 */
2224 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2225 (*Index == 0)) {
2226 _mesa_set_program_error (ctx, Program->Position,
2227 "Vertex program specified position invariance and wrote vertex position");
2228 _mesa_error (ctx, GL_INVALID_OPERATION,
2229 "Vertex program specified position invariance and wrote vertex position");
2230 }*/
2231
2232 /* And then the mask.
2233 * w,a -> bit 0
2234 * z,b -> bit 1
2235 * y,g -> bit 2
2236 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002237 *
2238 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002239 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002240 tmp = (GLint) *(*inst)++;
2241 *WriteMask = (((tmp>>3) & 0x1) |
2242 ((tmp>>1) & 0x2) |
2243 ((tmp<<1) & 0x4) |
2244 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002245
2246 return 0;
2247}
2248
2249
2250/**
2251 * Handle the parsing of a address register
2252 *
2253 * \param Index - The register index we write to
2254 *
2255 * \return 0 on sucess, 1 on error
2256 */
2257static GLuint
2258parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2259 struct var_cache **vc_head,
2260 struct arb_program *Program, GLint * Index)
2261{
2262 struct var_cache *dst;
2263 GLuint result;
Brian Paula6c423d2004-08-25 15:59:48 +00002264 (void) Index;
Jouk Jansen40322e12004-04-05 08:50:36 +00002265
2266 dst = parse_string (inst, vc_head, Program, &result);
2267 Program->Position = parse_position (inst);
2268
2269 /* If the name has never been added to our symbol table, we're hosed */
2270 if (!result) {
2271 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2272 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2273 dst->name);
2274 return 1;
2275 }
2276
2277 if (dst->type != vt_address) {
2278 _mesa_set_program_error (ctx, Program->Position,
2279 "Variable is not of type ADDRESS");
2280 _mesa_error (ctx, GL_INVALID_OPERATION,
2281 "Variable: %s is not of type ADDRESS", dst->name);
2282 return 1;
2283 }
2284
2285 return 0;
2286}
2287
Brian Paul8e8fa632005-07-01 02:03:33 +00002288#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002289/**
2290 * Handle the parsing out of a masked address register
2291 *
2292 * \param Index - The register index we write to
2293 * \param WriteMask - The mask controlling which components we write (1->write)
2294 *
2295 * \return 0 on sucess, 1 on error
2296 */
2297static GLuint
2298parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2299 struct var_cache **vc_head,
2300 struct arb_program *Program, GLint * Index,
2301 GLboolean * WriteMask)
2302{
2303 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2304 return 1;
2305
2306 /* This should be 0x8 */
2307 (*inst)++;
2308
2309 /* Writemask of .x is implied */
2310 WriteMask[0] = 1;
2311 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2312
2313 return 0;
2314}
Brian Paul8e8fa632005-07-01 02:03:33 +00002315#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002316
2317/**
2318 * Parse out a swizzle mask.
2319 *
Brian Paul32df89e2005-10-29 18:26:43 +00002320 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002321 *
2322 * The len parameter allows us to grab 4 components for a vector
2323 * swizzle, or just 1 component for a scalar src register selection
2324 */
Brian Paul32df89e2005-10-29 18:26:43 +00002325static void
2326parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002327{
Brian Paul32df89e2005-10-29 18:26:43 +00002328 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002329
Brian Paul32df89e2005-10-29 18:26:43 +00002330 for (i = 0; i < 4; i++)
2331 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002332
Brian Paul32df89e2005-10-29 18:26:43 +00002333 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002334 switch (*(*inst)++) {
2335 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002336 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002337 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002338 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002339 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002340 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002341 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002342 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002343 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002344 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002345 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002346 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002347 default:
2348 _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
2349 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002350 }
2351 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002352}
2353
Jouk Jansen40322e12004-04-05 08:50:36 +00002354
Brian Paul32df89e2005-10-29 18:26:43 +00002355/**
2356 * Parse an extended swizzle mask which is a sequence of
2357 * four x/y/z/w/0/1 tokens.
2358 * \return swizzle four swizzle values
2359 * \return negateMask four element bitfield
2360 */
2361static void
2362parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4],
2363 GLubyte *negateMask)
2364{
2365 GLint i;
2366
2367 *negateMask = 0x0;
2368 for (i = 0; i < 4; i++) {
2369 GLubyte swz;
2370 if (parse_sign(inst) == -1)
2371 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002372
2373 swz = *(*inst)++;
2374
2375 switch (swz) {
2376 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002377 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002378 break;
2379 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002380 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002381 break;
2382 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002383 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002384 break;
2385 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002386 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002387 break;
2388 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002389 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002390 break;
2391 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002392 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002393 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002394 default:
2395 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2396 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002397 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002398 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002399}
2400
2401
2402static GLuint
2403parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002404 struct arb_program *Program,
2405 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002406 GLboolean *IsRelOffset )
2407{
2408 struct var_cache *src;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002409 GLuint binding, is_generic, found;
Brian Paulbd997cd2004-07-20 21:12:56 +00002410 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002411
Keith Whitwell7c26b612005-04-21 14:46:57 +00002412 *IsRelOffset = 0;
2413
Jouk Jansen40322e12004-04-05 08:50:36 +00002414 /* And the binding for the src */
2415 switch (*(*inst)++) {
2416 case REGISTER_ATTRIB:
2417 if (parse_attrib_binding
Brian Paul18e7c5c2005-10-30 21:46:00 +00002418 (ctx, inst, Program, &binding, &is_generic))
Jouk Jansen40322e12004-04-05 08:50:36 +00002419 return 1;
2420 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002421 *Index = binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002422
2423 /* We need to insert a dummy variable into the var_cache so we can
2424 * catch generic vertex attrib aliasing errors
2425 */
2426 var_cache_create(&src);
2427 src->type = vt_attrib;
2428 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
Brian Paul18e7c5c2005-10-30 21:46:00 +00002429 src->attrib_binding = binding;
2430 src->attrib_is_generic = is_generic;
Jouk Jansen40322e12004-04-05 08:50:36 +00002431 var_cache_append(vc_head, src);
2432 if (generic_attrib_check(*vc_head)) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002433 const char *msg = "Cannot use both a generic vertex attribute "
2434 "and a specific attribute of the same type";
2435 _mesa_set_program_error (ctx, Program->Position, msg);
2436 _mesa_error (ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002437 return 1;
2438 }
2439 break;
2440
2441 case REGISTER_PARAM:
2442 switch (**inst) {
2443 case PARAM_ARRAY_ELEMENT:
2444 (*inst)++;
2445 src = parse_string (inst, vc_head, Program, &found);
2446 Program->Position = parse_position (inst);
2447
2448 if (!found) {
2449 _mesa_set_program_error (ctx, Program->Position,
2450 "2: Undefined variable");
2451 _mesa_error (ctx, GL_INVALID_OPERATION,
2452 "2: Undefined variable: %s", src->name);
2453 return 1;
2454 }
2455
2456 *File = src->param_binding_type;
2457
2458 switch (*(*inst)++) {
2459 case ARRAY_INDEX_ABSOLUTE:
2460 offset = parse_integer (inst, Program);
2461
2462 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002463 || (offset >= (int)src->param_binding_length)) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002464 _mesa_set_program_error (ctx, Program->Position,
2465 "Index out of range");
2466 _mesa_error (ctx, GL_INVALID_OPERATION,
2467 "Index %d out of range for %s", offset,
2468 src->name);
2469 return 1;
2470 }
2471
2472 *Index = src->param_binding_begin + offset;
2473 break;
2474
2475 case ARRAY_INDEX_RELATIVE:
2476 {
2477 GLint addr_reg_idx, rel_off;
2478
2479 /* First, grab the address regiseter */
2480 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2481 return 1;
2482
2483 /* And the .x */
2484 ((*inst)++);
2485 ((*inst)++);
2486 ((*inst)++);
2487 ((*inst)++);
2488
2489 /* Then the relative offset */
2490 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2491
2492 /* And store it properly */
2493 *Index = src->param_binding_begin + rel_off;
2494 *IsRelOffset = 1;
2495 }
2496 break;
2497 }
2498 break;
2499
2500 default:
Jouk Jansen40322e12004-04-05 08:50:36 +00002501 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2502 return 1;
2503
2504 *File = src->param_binding_type;
2505 *Index = src->param_binding_begin;
2506 break;
2507 }
2508 break;
2509
2510 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002511 src = parse_string (inst, vc_head, Program, &found);
2512 Program->Position = parse_position (inst);
2513
2514 /* If the name has never been added to our symbol table, we're hosed */
2515 if (!found) {
2516 _mesa_set_program_error (ctx, Program->Position,
2517 "3: Undefined variable");
2518 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2519 src->name);
2520 return 1;
2521 }
2522
2523 switch (src->type) {
2524 case vt_attrib:
2525 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002526 *Index = src->attrib_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002527 break;
2528
2529 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2530 case vt_param:
2531 *File = src->param_binding_type;
2532 *Index = src->param_binding_begin;
2533 break;
2534
2535 case vt_temp:
2536 *File = PROGRAM_TEMPORARY;
2537 *Index = src->temp_binding;
2538 break;
2539
2540 /* If the var type is vt_output no go */
2541 default:
2542 _mesa_set_program_error (ctx, Program->Position,
2543 "destination register is read only");
2544 _mesa_error (ctx, GL_INVALID_OPERATION,
2545 "destination register is read only: %s",
2546 src->name);
2547 return 1;
2548 }
2549 break;
2550
2551 default:
2552 _mesa_set_program_error (ctx, Program->Position,
2553 "Unknown token in parse_src_reg");
2554 _mesa_error (ctx, GL_INVALID_OPERATION,
2555 "Unknown token in parse_src_reg");
2556 return 1;
2557 }
2558
2559 return 0;
2560}
2561
2562/**
Brian Paul18e7c5c2005-10-30 21:46:00 +00002563 * Parse fragment program vector source register.
Jouk Jansen40322e12004-04-05 08:50:36 +00002564 */
2565static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00002566parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
2567 struct var_cache **vc_head,
2568 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00002569 struct prog_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002570{
Brian Paul7aebaf32005-10-30 21:23:23 +00002571 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002572 GLint index;
2573 GLboolean negate;
2574 GLubyte swizzle[4];
2575 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002576
Jouk Jansen40322e12004-04-05 08:50:36 +00002577 /* Grab the sign */
Brian Paul32df89e2005-10-29 18:26:43 +00002578 negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002579
2580 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002581 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002582 return 1;
2583
2584 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002585 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002586
Brian Paul32df89e2005-10-29 18:26:43 +00002587 reg->File = file;
2588 reg->Index = index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002589 reg->Abs = 0; /* NV only */
2590 reg->NegateAbs = 0; /* NV only */
Brian Paul32df89e2005-10-29 18:26:43 +00002591 reg->NegateBase = negate;
2592 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00002593 return 0;
2594}
2595
Jouk Jansen40322e12004-04-05 08:50:36 +00002596
Keith Whitwell7c26b612005-04-21 14:46:57 +00002597static GLuint
2598parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
2599 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002600 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002601{
Brian Paul7aebaf32005-10-30 21:23:23 +00002602 GLint mask;
2603 GLuint idx;
2604 enum register_file file;
2605
Keith Whitwell7c26b612005-04-21 14:46:57 +00002606 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002607 return 1;
2608
Keith Whitwell7c26b612005-04-21 14:46:57 +00002609 reg->CondMask = 0; /* NV only */
2610 reg->CondSwizzle = 0; /* NV only */
2611 reg->File = file;
2612 reg->Index = idx;
2613 reg->WriteMask = mask;
2614 return 0;
2615}
2616
2617
Brian Paul7aebaf32005-10-30 21:23:23 +00002618/**
2619 * Parse fragment program scalar src register.
2620 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002621static GLuint
2622parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00002623 struct var_cache **vc_head,
2624 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002625 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002626{
Brian Paul7aebaf32005-10-30 21:23:23 +00002627 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002628 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00002629 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002630 GLubyte Swizzle[4];
2631 GLboolean IsRelOffset;
2632
2633 /* Grab the sign */
2634 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2635
2636 /* And the src reg */
2637 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2638 return 1;
2639
2640 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002641 parse_swizzle_mask(inst, Swizzle, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002642
Keith Whitwell7c26b612005-04-21 14:46:57 +00002643 reg->File = File;
2644 reg->Index = Index;
2645 reg->Abs = 0; /* NV only */
2646 reg->NegateAbs = 0; /* NV only */
2647 reg->NegateBase = Negate;
2648 reg->Swizzle = (Swizzle[0] << 0);
2649
Jouk Jansen40322e12004-04-05 08:50:36 +00002650 return 0;
2651}
2652
Keith Whitwell7c26b612005-04-21 14:46:57 +00002653
Jouk Jansen40322e12004-04-05 08:50:36 +00002654/**
2655 * This is a big mother that handles getting opcodes into the instruction
2656 * and handling the src & dst registers for fragment program instructions
2657 */
2658static GLuint
2659parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2660 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002661 struct prog_instruction *fp)
Jouk Jansen40322e12004-04-05 08:50:36 +00002662{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002663 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002664 GLuint texcoord;
2665 GLubyte instClass, type, code;
2666 GLboolean rel;
2667
Brian Paul7e807512005-11-05 17:10:45 +00002668 _mesa_init_instruction(fp);
Jouk Jansen40322e12004-04-05 08:50:36 +00002669
2670 /* Record the position in the program string for debugging */
2671 fp->StringPos = Program->Position;
2672
2673 /* OP_ALU_INST or OP_TEX_INST */
2674 instClass = *(*inst)++;
2675
2676 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2677 * OP_TEX_{SAMPLE, KIL}
2678 */
2679 type = *(*inst)++;
2680
2681 /* The actual opcode name */
2682 code = *(*inst)++;
2683
2684 /* Increment the correct count */
2685 switch (instClass) {
2686 case OP_ALU_INST:
2687 Program->NumAluInstructions++;
2688 break;
2689 case OP_TEX_INST:
2690 Program->NumTexInstructions++;
2691 break;
2692 }
2693
Jouk Jansen40322e12004-04-05 08:50:36 +00002694 switch (type) {
2695 case OP_ALU_VECTOR:
2696 switch (code) {
2697 case OP_ABS_SAT:
2698 fp->Saturate = 1;
2699 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00002700 fp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002701 break;
2702
2703 case OP_FLR_SAT:
2704 fp->Saturate = 1;
2705 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00002706 fp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00002707 break;
2708
2709 case OP_FRC_SAT:
2710 fp->Saturate = 1;
2711 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00002712 fp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00002713 break;
2714
2715 case OP_LIT_SAT:
2716 fp->Saturate = 1;
2717 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00002718 fp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002719 break;
2720
2721 case OP_MOV_SAT:
2722 fp->Saturate = 1;
2723 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00002724 fp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00002725 break;
2726 }
2727
Keith Whitwell7c26b612005-04-21 14:46:57 +00002728 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002729 return 1;
2730
Keith Whitwell7c26b612005-04-21 14:46:57 +00002731 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002732 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002733 break;
2734
2735 case OP_ALU_SCALAR:
2736 switch (code) {
2737 case OP_COS_SAT:
2738 fp->Saturate = 1;
2739 case OP_COS:
Brian Paul7e807512005-11-05 17:10:45 +00002740 fp->Opcode = OPCODE_COS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002741 break;
2742
2743 case OP_EX2_SAT:
2744 fp->Saturate = 1;
2745 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00002746 fp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002747 break;
2748
2749 case OP_LG2_SAT:
2750 fp->Saturate = 1;
2751 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00002752 fp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002753 break;
2754
2755 case OP_RCP_SAT:
2756 fp->Saturate = 1;
2757 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00002758 fp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002759 break;
2760
2761 case OP_RSQ_SAT:
2762 fp->Saturate = 1;
2763 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00002764 fp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002765 break;
2766
2767 case OP_SIN_SAT:
2768 fp->Saturate = 1;
2769 case OP_SIN:
Brian Paul7e807512005-11-05 17:10:45 +00002770 fp->Opcode = OPCODE_SIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002771 break;
2772
2773 case OP_SCS_SAT:
2774 fp->Saturate = 1;
2775 case OP_SCS:
2776
Brian Paul7e807512005-11-05 17:10:45 +00002777 fp->Opcode = OPCODE_SCS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002778 break;
2779 }
2780
Keith Whitwell7c26b612005-04-21 14:46:57 +00002781 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002782 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002783
2784 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002785 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002786 break;
2787
2788 case OP_ALU_BINSC:
2789 switch (code) {
2790 case OP_POW_SAT:
2791 fp->Saturate = 1;
2792 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00002793 fp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00002794 break;
2795 }
2796
Keith Whitwell7c26b612005-04-21 14:46:57 +00002797 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002798 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002799
Jouk Jansen40322e12004-04-05 08:50:36 +00002800 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002801 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002802 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002803 }
2804 break;
2805
2806
2807 case OP_ALU_BIN:
2808 switch (code) {
2809 case OP_ADD_SAT:
2810 fp->Saturate = 1;
2811 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00002812 fp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002813 break;
2814
2815 case OP_DP3_SAT:
2816 fp->Saturate = 1;
2817 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00002818 fp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00002819 break;
2820
2821 case OP_DP4_SAT:
2822 fp->Saturate = 1;
2823 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00002824 fp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00002825 break;
2826
2827 case OP_DPH_SAT:
2828 fp->Saturate = 1;
2829 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00002830 fp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00002831 break;
2832
2833 case OP_DST_SAT:
2834 fp->Saturate = 1;
2835 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00002836 fp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00002837 break;
2838
2839 case OP_MAX_SAT:
2840 fp->Saturate = 1;
2841 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00002842 fp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002843 break;
2844
2845 case OP_MIN_SAT:
2846 fp->Saturate = 1;
2847 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00002848 fp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002849 break;
2850
2851 case OP_MUL_SAT:
2852 fp->Saturate = 1;
2853 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00002854 fp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00002855 break;
2856
2857 case OP_SGE_SAT:
2858 fp->Saturate = 1;
2859 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00002860 fp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002861 break;
2862
2863 case OP_SLT_SAT:
2864 fp->Saturate = 1;
2865 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00002866 fp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002867 break;
2868
2869 case OP_SUB_SAT:
2870 fp->Saturate = 1;
2871 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00002872 fp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002873 break;
2874
2875 case OP_XPD_SAT:
2876 fp->Saturate = 1;
2877 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00002878 fp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002879 break;
2880 }
2881
Keith Whitwell7c26b612005-04-21 14:46:57 +00002882 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002883 return 1;
2884 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002885 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2886 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002887 }
2888 break;
2889
2890 case OP_ALU_TRI:
2891 switch (code) {
2892 case OP_CMP_SAT:
2893 fp->Saturate = 1;
2894 case OP_CMP:
Brian Paul7e807512005-11-05 17:10:45 +00002895 fp->Opcode = OPCODE_CMP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002896 break;
2897
2898 case OP_LRP_SAT:
2899 fp->Saturate = 1;
2900 case OP_LRP:
Brian Paul7e807512005-11-05 17:10:45 +00002901 fp->Opcode = OPCODE_LRP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002902 break;
2903
2904 case OP_MAD_SAT:
2905 fp->Saturate = 1;
2906 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00002907 fp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002908 break;
2909 }
2910
Keith Whitwell7c26b612005-04-21 14:46:57 +00002911 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002912 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002913
Jouk Jansen40322e12004-04-05 08:50:36 +00002914 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002915 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2916 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002917 }
2918 break;
2919
2920 case OP_ALU_SWZ:
2921 switch (code) {
2922 case OP_SWZ_SAT:
2923 fp->Saturate = 1;
2924 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00002925 fp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002926 break;
2927 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00002928 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002929 return 1;
2930
Keith Whitwell7c26b612005-04-21 14:46:57 +00002931 {
Brian Paul32df89e2005-10-29 18:26:43 +00002932 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002933 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002934 enum register_file file;
2935 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002936
Brian Paul32df89e2005-10-29 18:26:43 +00002937 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002938 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00002939 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
2940 fp->SrcReg[0].File = file;
2941 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00002942 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002943 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
2944 swizzle[1],
2945 swizzle[2],
2946 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00002947 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002948 break;
2949
2950 case OP_TEX_SAMPLE:
2951 switch (code) {
2952 case OP_TEX_SAT:
2953 fp->Saturate = 1;
2954 case OP_TEX:
Brian Paul7e807512005-11-05 17:10:45 +00002955 fp->Opcode = OPCODE_TEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002956 break;
2957
2958 case OP_TXP_SAT:
2959 fp->Saturate = 1;
2960 case OP_TXP:
Brian Paul7e807512005-11-05 17:10:45 +00002961 fp->Opcode = OPCODE_TXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002962 break;
2963
2964 case OP_TXB_SAT:
Jouk Jansen40322e12004-04-05 08:50:36 +00002965 fp->Saturate = 1;
2966 case OP_TXB:
Brian Paul7e807512005-11-05 17:10:45 +00002967 fp->Opcode = OPCODE_TXB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002968 break;
2969 }
2970
Keith Whitwell7c26b612005-04-21 14:46:57 +00002971 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002972 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002973
2974 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002975 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002976
2977 /* texImageUnit */
2978 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
2979 return 1;
2980 fp->TexSrcUnit = texcoord;
2981
2982 /* texTarget */
2983 switch (*(*inst)++) {
2984 case TEXTARGET_1D:
Brian Paul7e807512005-11-05 17:10:45 +00002985 fp->TexSrcTarget = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002986 break;
2987 case TEXTARGET_2D:
Brian Paul7e807512005-11-05 17:10:45 +00002988 fp->TexSrcTarget = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002989 break;
2990 case TEXTARGET_3D:
Brian Paul7e807512005-11-05 17:10:45 +00002991 fp->TexSrcTarget = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002992 break;
2993 case TEXTARGET_RECT:
Brian Paul7e807512005-11-05 17:10:45 +00002994 fp->TexSrcTarget = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002995 break;
2996 case TEXTARGET_CUBE:
Brian Paul7e807512005-11-05 17:10:45 +00002997 fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002998 break;
2999 case TEXTARGET_SHADOW1D:
3000 case TEXTARGET_SHADOW2D:
3001 case TEXTARGET_SHADOWRECT:
3002 /* TODO ARB_fragment_program_shadow code */
3003 break;
3004 }
Brian Paul7e807512005-11-05 17:10:45 +00003005 Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcTarget);
Jouk Jansen40322e12004-04-05 08:50:36 +00003006 break;
3007
3008 case OP_TEX_KIL:
Keith Whitwellc3626a92005-11-01 17:25:49 +00003009 Program->UsesKill = 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003010 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003011 return 1;
Brian Paul7e807512005-11-05 17:10:45 +00003012 fp->Opcode = OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003013 break;
3014 }
3015
3016 return 0;
3017}
3018
Keith Whitwell7c26b612005-04-21 14:46:57 +00003019static GLuint
3020parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
3021 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003022 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003023{
Brian Paul7aebaf32005-10-30 21:23:23 +00003024 GLint mask;
3025 GLuint idx;
3026 enum register_file file;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003027
3028 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3029 return 1;
3030
3031 reg->File = file;
3032 reg->Index = idx;
3033 reg->WriteMask = mask;
3034 return 0;
3035}
3036
3037/**
3038 * Handle the parsing out of a masked address register
3039 *
3040 * \param Index - The register index we write to
3041 * \param WriteMask - The mask controlling which components we write (1->write)
3042 *
3043 * \return 0 on sucess, 1 on error
3044 */
3045static GLuint
3046parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
3047 struct var_cache **vc_head,
3048 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003049 struct prog_dst_register *reg)
Keith Whitwell7c26b612005-04-21 14:46:57 +00003050{
3051 GLint idx;
3052
3053 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3054 return 1;
3055
3056 /* This should be 0x8 */
3057 (*inst)++;
3058
3059 reg->File = PROGRAM_ADDRESS;
3060 reg->Index = idx;
3061
3062 /* Writemask of .x is implied */
3063 reg->WriteMask = 0x1;
3064 return 0;
3065}
3066
3067/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003068 * Parse vertex program vector source register.
Keith Whitwell7c26b612005-04-21 14:46:57 +00003069 */
3070static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00003071parse_vp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
3072 struct var_cache **vc_head,
3073 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00003074 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003075{
Brian Paul7aebaf32005-10-30 21:23:23 +00003076 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00003077 GLint index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003078 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003079 GLubyte swizzle[4];
3080 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003081
3082 /* Grab the sign */
Brian Paul7aebaf32005-10-30 21:23:23 +00003083 negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003084
3085 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00003086 if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003087 return 1;
3088
3089 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003090 parse_swizzle_mask(inst, swizzle, 4);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003091
Brian Paul32df89e2005-10-29 18:26:43 +00003092 reg->File = file;
3093 reg->Index = index;
3094 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
3095 swizzle[2], swizzle[3]);
Brian Paul7e807512005-11-05 17:10:45 +00003096 reg->NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003097 reg->RelAddr = isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003098 return 0;
3099}
3100
3101
3102static GLuint
3103parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00003104 struct var_cache **vc_head,
3105 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003106 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003107{
Brian Paul7aebaf32005-10-30 21:23:23 +00003108 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003109 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003110 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003111 GLubyte Swizzle[4];
3112 GLboolean IsRelOffset;
3113
3114 /* Grab the sign */
3115 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3116
3117 /* And the src reg */
3118 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3119 return 1;
3120
3121 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003122 parse_swizzle_mask(inst, Swizzle, 1);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003123
3124 reg->File = File;
3125 reg->Index = Index;
3126 reg->Swizzle = (Swizzle[0] << 0);
Brian Paul7e807512005-11-05 17:10:45 +00003127 reg->NegateBase = Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003128 reg->RelAddr = IsRelOffset;
3129 return 0;
3130}
3131
3132
Jouk Jansen40322e12004-04-05 08:50:36 +00003133/**
3134 * This is a big mother that handles getting opcodes into the instruction
3135 * and handling the src & dst registers for vertex program instructions
3136 */
3137static GLuint
3138parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3139 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003140 struct prog_instruction *vp)
Jouk Jansen40322e12004-04-05 08:50:36 +00003141{
3142 GLint a;
3143 GLubyte type, code;
3144
3145 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3146 type = *(*inst)++;
3147
3148 /* The actual opcode name */
3149 code = *(*inst)++;
3150
Brian Paul7e807512005-11-05 17:10:45 +00003151 _mesa_init_instruction(vp);
Jouk Jansen40322e12004-04-05 08:50:36 +00003152 /* Record the position in the program string for debugging */
3153 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003154
3155 switch (type) {
3156 /* XXX: */
3157 case OP_ALU_ARL:
Brian Paul7e807512005-11-05 17:10:45 +00003158 vp->Opcode = OPCODE_ARL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003159
3160 /* Remember to set SrcReg.RelAddr; */
3161
3162 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003163 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003164 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003165
Jouk Jansen40322e12004-04-05 08:50:36 +00003166 vp->DstReg.File = PROGRAM_ADDRESS;
3167
3168 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003169 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003170 return 1;
3171
3172 break;
3173
3174 case OP_ALU_VECTOR:
3175 switch (code) {
3176 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00003177 vp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00003178 break;
3179 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00003180 vp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00003181 break;
3182 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00003183 vp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00003184 break;
3185 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00003186 vp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003187 break;
3188 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00003189 vp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00003190 break;
3191 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003192
3193 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003194 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003195
3196 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003197 return 1;
3198 break;
3199
3200 case OP_ALU_SCALAR:
3201 switch (code) {
3202 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00003203 vp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003204 break;
3205 case OP_EXP:
Brian Paul7e807512005-11-05 17:10:45 +00003206 vp->Opcode = OPCODE_EXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003207 break;
3208 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00003209 vp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003210 break;
3211 case OP_LOG:
Brian Paul7e807512005-11-05 17:10:45 +00003212 vp->Opcode = OPCODE_LOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00003213 break;
3214 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00003215 vp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003216 break;
3217 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00003218 vp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003219 break;
3220 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003221 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003222 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003223
3224 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003225 return 1;
3226 break;
3227
3228 case OP_ALU_BINSC:
3229 switch (code) {
3230 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00003231 vp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00003232 break;
3233 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003234 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003235 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003236
Jouk Jansen40322e12004-04-05 08:50:36 +00003237 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003238 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003239 return 1;
3240 }
3241 break;
3242
3243 case OP_ALU_BIN:
3244 switch (code) {
3245 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00003246 vp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003247 break;
3248 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00003249 vp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00003250 break;
3251 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00003252 vp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00003253 break;
3254 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00003255 vp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00003256 break;
3257 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00003258 vp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00003259 break;
3260 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00003261 vp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003262 break;
3263 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00003264 vp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00003265 break;
3266 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00003267 vp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003268 break;
3269 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00003270 vp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003271 break;
3272 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00003273 vp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003274 break;
3275 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00003276 vp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003277 break;
3278 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00003279 vp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003280 break;
3281 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003282 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003283 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003284
Jouk Jansen40322e12004-04-05 08:50:36 +00003285 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003286 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003287 return 1;
3288 }
3289 break;
3290
3291 case OP_ALU_TRI:
3292 switch (code) {
3293 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00003294 vp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003295 break;
3296 }
3297
Keith Whitwell7c26b612005-04-21 14:46:57 +00003298 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003299 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003300
Jouk Jansen40322e12004-04-05 08:50:36 +00003301 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003302 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003303 return 1;
3304 }
3305 break;
3306
3307 case OP_ALU_SWZ:
3308 switch (code) {
3309 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00003310 vp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003311 break;
3312 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003313 {
Brian Paul32df89e2005-10-29 18:26:43 +00003314 GLubyte swizzle[4];
3315 GLubyte negateMask;
3316 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003317 enum register_file file;
3318 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003319
Keith Whitwell7c26b612005-04-21 14:46:57 +00003320 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3321 return 1;
3322
Brian Paul32df89e2005-10-29 18:26:43 +00003323 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003324 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003325 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3326 vp->SrcReg[0].File = file;
3327 vp->SrcReg[0].Index = index;
Brian Paul7e807512005-11-05 17:10:45 +00003328 vp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003329 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3330 swizzle[1],
3331 swizzle[2],
3332 swizzle[3]);
3333 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003334 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003335 break;
3336 }
3337 return 0;
3338}
3339
3340#if DEBUG_PARSING
3341
3342static GLvoid
3343print_state_token (GLint token)
3344{
3345 switch (token) {
3346 case STATE_MATERIAL:
3347 fprintf (stderr, "STATE_MATERIAL ");
3348 break;
3349 case STATE_LIGHT:
3350 fprintf (stderr, "STATE_LIGHT ");
3351 break;
3352
3353 case STATE_LIGHTMODEL_AMBIENT:
3354 fprintf (stderr, "STATE_AMBIENT ");
3355 break;
3356
3357 case STATE_LIGHTMODEL_SCENECOLOR:
3358 fprintf (stderr, "STATE_SCENECOLOR ");
3359 break;
3360
3361 case STATE_LIGHTPROD:
3362 fprintf (stderr, "STATE_LIGHTPROD ");
3363 break;
3364
3365 case STATE_TEXGEN:
3366 fprintf (stderr, "STATE_TEXGEN ");
3367 break;
3368
3369 case STATE_FOG_COLOR:
3370 fprintf (stderr, "STATE_FOG_COLOR ");
3371 break;
3372
3373 case STATE_FOG_PARAMS:
3374 fprintf (stderr, "STATE_FOG_PARAMS ");
3375 break;
3376
3377 case STATE_CLIPPLANE:
3378 fprintf (stderr, "STATE_CLIPPLANE ");
3379 break;
3380
3381 case STATE_POINT_SIZE:
3382 fprintf (stderr, "STATE_POINT_SIZE ");
3383 break;
3384
3385 case STATE_POINT_ATTENUATION:
3386 fprintf (stderr, "STATE_ATTENUATION ");
3387 break;
3388
3389 case STATE_MATRIX:
3390 fprintf (stderr, "STATE_MATRIX ");
3391 break;
3392
3393 case STATE_MODELVIEW:
3394 fprintf (stderr, "STATE_MODELVIEW ");
3395 break;
3396
3397 case STATE_PROJECTION:
3398 fprintf (stderr, "STATE_PROJECTION ");
3399 break;
3400
3401 case STATE_MVP:
3402 fprintf (stderr, "STATE_MVP ");
3403 break;
3404
3405 case STATE_TEXTURE:
3406 fprintf (stderr, "STATE_TEXTURE ");
3407 break;
3408
3409 case STATE_PROGRAM:
3410 fprintf (stderr, "STATE_PROGRAM ");
3411 break;
3412
3413 case STATE_MATRIX_INVERSE:
3414 fprintf (stderr, "STATE_INVERSE ");
3415 break;
3416
3417 case STATE_MATRIX_TRANSPOSE:
3418 fprintf (stderr, "STATE_TRANSPOSE ");
3419 break;
3420
3421 case STATE_MATRIX_INVTRANS:
3422 fprintf (stderr, "STATE_INVTRANS ");
3423 break;
3424
3425 case STATE_AMBIENT:
3426 fprintf (stderr, "STATE_AMBIENT ");
3427 break;
3428
3429 case STATE_DIFFUSE:
3430 fprintf (stderr, "STATE_DIFFUSE ");
3431 break;
3432
3433 case STATE_SPECULAR:
3434 fprintf (stderr, "STATE_SPECULAR ");
3435 break;
3436
3437 case STATE_EMISSION:
3438 fprintf (stderr, "STATE_EMISSION ");
3439 break;
3440
3441 case STATE_SHININESS:
3442 fprintf (stderr, "STATE_SHININESS ");
3443 break;
3444
3445 case STATE_HALF:
3446 fprintf (stderr, "STATE_HALF ");
3447 break;
3448
3449 case STATE_POSITION:
3450 fprintf (stderr, "STATE_POSITION ");
3451 break;
3452
3453 case STATE_ATTENUATION:
3454 fprintf (stderr, "STATE_ATTENUATION ");
3455 break;
3456
3457 case STATE_SPOT_DIRECTION:
3458 fprintf (stderr, "STATE_DIRECTION ");
3459 break;
3460
3461 case STATE_TEXGEN_EYE_S:
3462 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3463 break;
3464
3465 case STATE_TEXGEN_EYE_T:
3466 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3467 break;
3468
3469 case STATE_TEXGEN_EYE_R:
3470 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3471 break;
3472
3473 case STATE_TEXGEN_EYE_Q:
3474 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3475 break;
3476
3477 case STATE_TEXGEN_OBJECT_S:
3478 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3479 break;
3480
3481 case STATE_TEXGEN_OBJECT_T:
3482 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3483 break;
3484
3485 case STATE_TEXGEN_OBJECT_R:
3486 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3487 break;
3488
3489 case STATE_TEXGEN_OBJECT_Q:
3490 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3491 break;
3492
3493 case STATE_TEXENV_COLOR:
3494 fprintf (stderr, "STATE_TEXENV_COLOR ");
3495 break;
3496
3497 case STATE_DEPTH_RANGE:
3498 fprintf (stderr, "STATE_DEPTH_RANGE ");
3499 break;
3500
3501 case STATE_VERTEX_PROGRAM:
3502 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3503 break;
3504
3505 case STATE_FRAGMENT_PROGRAM:
3506 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3507 break;
3508
3509 case STATE_ENV:
3510 fprintf (stderr, "STATE_ENV ");
3511 break;
3512
3513 case STATE_LOCAL:
3514 fprintf (stderr, "STATE_LOCAL ");
3515 break;
3516
3517 }
3518 fprintf (stderr, "[%d] ", token);
3519}
3520
3521
3522static GLvoid
3523debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3524 struct arb_program *Program)
3525{
3526 struct var_cache *vc;
3527 GLint a, b;
3528
3529 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3530
3531 /* First of all, print out the contents of the var_cache */
3532 vc = vc_head;
3533 while (vc) {
3534 fprintf (stderr, "[%x]\n", vc);
3535 switch (vc->type) {
3536 case vt_none:
3537 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3538 break;
3539 case vt_attrib:
3540 fprintf (stderr, "ATTRIB %s\n", vc->name);
3541 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3542 break;
3543 case vt_param:
3544 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3545 vc->param_binding_begin, vc->param_binding_length);
3546 b = vc->param_binding_begin;
3547 for (a = 0; a < vc->param_binding_length; a++) {
3548 fprintf (stderr, "%s\n",
3549 Program->Parameters->Parameters[a + b].Name);
3550 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3551 print_state_token (Program->Parameters->Parameters[a + b].
3552 StateIndexes[0]);
3553 print_state_token (Program->Parameters->Parameters[a + b].
3554 StateIndexes[1]);
3555 print_state_token (Program->Parameters->Parameters[a + b].
3556 StateIndexes[2]);
3557 print_state_token (Program->Parameters->Parameters[a + b].
3558 StateIndexes[3]);
3559 print_state_token (Program->Parameters->Parameters[a + b].
3560 StateIndexes[4]);
3561 print_state_token (Program->Parameters->Parameters[a + b].
3562 StateIndexes[5]);
3563 }
3564 else
3565 fprintf (stderr, "%f %f %f %f\n",
3566 Program->Parameters->Parameters[a + b].Values[0],
3567 Program->Parameters->Parameters[a + b].Values[1],
3568 Program->Parameters->Parameters[a + b].Values[2],
3569 Program->Parameters->Parameters[a + b].Values[3]);
3570 }
3571 break;
3572 case vt_temp:
3573 fprintf (stderr, "TEMP %s\n", vc->name);
3574 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3575 break;
3576 case vt_output:
3577 fprintf (stderr, "OUTPUT %s\n", vc->name);
3578 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3579 break;
3580 case vt_alias:
3581 fprintf (stderr, "ALIAS %s\n", vc->name);
3582 fprintf (stderr, " binding: 0x%x (%s)\n",
3583 vc->alias_binding, vc->alias_binding->name);
3584 break;
3585 }
3586 vc = vc->next;
3587 }
3588}
3589
Brian Paul72030e02005-11-03 03:30:34 +00003590#endif /* DEBUG_PARSING */
Brian Paul7aebaf32005-10-30 21:23:23 +00003591
3592
3593/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003594 * The main loop for parsing a fragment or vertex program
3595 *
Brian Paul72030e02005-11-03 03:30:34 +00003596 * \return 1 on error, 0 on success
Jouk Jansen40322e12004-04-05 08:50:36 +00003597 */
Brian Paul72030e02005-11-03 03:30:34 +00003598static GLint
Brian Paul45703642005-10-29 15:52:31 +00003599parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3600 struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003601{
Brian Paul72030e02005-11-03 03:30:34 +00003602 const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
3603 ? ctx->Const.FragmentProgram.MaxInstructions
3604 : ctx->Const.VertexProgram.MaxInstructions;
Jouk Jansen40322e12004-04-05 08:50:36 +00003605 GLint err = 0;
3606
Brian Paul72030e02005-11-03 03:30:34 +00003607 ASSERT(MAX_INSTRUCTIONS >= maxInst);
3608
Jouk Jansen40322e12004-04-05 08:50:36 +00003609 Program->MajorVersion = (GLuint) * inst++;
3610 Program->MinorVersion = (GLuint) * inst++;
3611
3612 while (*inst != END) {
3613 switch (*inst++) {
3614
3615 case OPTION:
3616 switch (*inst++) {
3617 case ARB_PRECISION_HINT_FASTEST:
3618 Program->PrecisionOption = GL_FASTEST;
3619 break;
3620
3621 case ARB_PRECISION_HINT_NICEST:
3622 Program->PrecisionOption = GL_NICEST;
3623 break;
3624
3625 case ARB_FOG_EXP:
3626 Program->FogOption = GL_EXP;
3627 break;
3628
3629 case ARB_FOG_EXP2:
3630 Program->FogOption = GL_EXP2;
3631 break;
3632
3633 case ARB_FOG_LINEAR:
3634 Program->FogOption = GL_LINEAR;
3635 break;
3636
3637 case ARB_POSITION_INVARIANT:
3638 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
Brian Paul45cd2f92005-11-03 02:25:10 +00003639 Program->HintPositionInvariant = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003640 break;
3641
3642 case ARB_FRAGMENT_PROGRAM_SHADOW:
3643 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3644 /* TODO ARB_fragment_program_shadow code */
3645 }
3646 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003647
3648 case ARB_DRAW_BUFFERS:
3649 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3650 /* do nothing for now */
3651 }
3652 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003653 }
3654 break;
3655
3656 case INSTRUCTION:
Brian Paul72030e02005-11-03 03:30:34 +00003657 /* check length */
3658 if (Program->Base.NumInstructions + 1 >= maxInst) {
3659 const char *msg = "Max instruction count exceeded";
3660 _mesa_set_program_error(ctx, Program->Position, msg);
3661 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
3662 return 1;
3663 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003664 Program->Position = parse_position (&inst);
Brian Paul72030e02005-11-03 03:30:34 +00003665 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003666 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003667 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003668 &Program->FPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003669 }
3670 else {
Jouk Jansen40322e12004-04-05 08:50:36 +00003671 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003672 &Program->VPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003673 }
3674
Brian Paul72030e02005-11-03 03:30:34 +00003675 /* increment instuction count */
Jouk Jansen40322e12004-04-05 08:50:36 +00003676 Program->Base.NumInstructions++;
3677 break;
3678
3679 case DECLARATION:
3680 err = parse_declaration (ctx, &inst, vc_head, Program);
3681 break;
3682
3683 default:
3684 break;
3685 }
3686
3687 if (err)
3688 break;
3689 }
3690
3691 /* Finally, tag on an OPCODE_END instruction */
3692 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00003693 const GLuint numInst = Program->Base.NumInstructions;
Brian Paul7e807512005-11-05 17:10:45 +00003694 _mesa_init_instruction(Program->FPInstructions + numInst);
3695 Program->FPInstructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003696 /* YYY Wrong Position in program, whatever, at least not random -> crash
3697 Program->Position = parse_position (&inst);
3698 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003699 Program->FPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003700 }
3701 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00003702 const GLuint numInst = Program->Base.NumInstructions;
Brian Paul7e807512005-11-05 17:10:45 +00003703 _mesa_init_instruction(Program->VPInstructions + numInst);
3704 Program->VPInstructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003705 /* YYY Wrong Position in program, whatever, at least not random -> crash
3706 Program->Position = parse_position (&inst);
3707 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003708 Program->VPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003709 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003710 Program->Base.NumInstructions++;
3711
Brian Paul05051032005-11-01 04:36:33 +00003712 /*
3713 * Initialize native counts to logical counts. The device driver may
3714 * change them if program is translated into a hardware program.
3715 */
3716 Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
3717 Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
3718 Program->Base.NumNativeParameters = Program->Base.NumParameters;
3719 Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
3720 Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
3721 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3722 struct fragment_program *fp = (struct fragment_program *) Program;
3723 fp->NumNativeAluInstructions = fp->NumAluInstructions;
3724 fp->NumNativeTexInstructions = fp->NumTexInstructions;
3725 fp->NumNativeTexIndirections = fp->NumTexIndirections;
3726 }
3727
Jouk Jansen40322e12004-04-05 08:50:36 +00003728 return err;
3729}
3730
Brian Paul7aebaf32005-10-30 21:23:23 +00003731
Jouk Jansen40322e12004-04-05 08:50:36 +00003732/* XXX temporary */
Brian Paula6c423d2004-08-25 15:59:48 +00003733__extension__ static char core_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +00003734#include "grammar_syn.h"
3735;
3736
Brian Paul7aebaf32005-10-30 21:23:23 +00003737
Jouk Jansen40322e12004-04-05 08:50:36 +00003738static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3739{
3740 char error_msg[300];
3741 GLint error_pos;
3742
3743 if (grammar_set_reg8 (id, name, value))
3744 return 0;
3745
3746 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3747 _mesa_set_program_error (ctx, error_pos, error_msg);
3748 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3749 return 1;
3750}
3751
3752static int extension_is_supported (const GLubyte *ext)
3753{
Brian Paul832026f2005-11-08 14:41:41 +00003754 const GLubyte *extensions = _mesa_GetString(GL_EXTENSIONS);
Jouk Jansen40322e12004-04-05 08:50:36 +00003755 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
Karl Schultz6258b762005-05-05 21:08:07 +00003756 const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
Jouk Jansen40322e12004-04-05 08:50:36 +00003757
3758 while (extensions < end)
3759 {
Brian Paulb3aefd12005-09-19 20:12:32 +00003760 const GLubyte *name_end = (const GLubyte *) _mesa_strstr ((const char *) extensions, " ");
Jouk Jansen40322e12004-04-05 08:50:36 +00003761 if (name_end == NULL)
3762 name_end = end;
3763 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3764 (const char *) extensions, ext_len) == 0)
3765 return 1;
3766 extensions = name_end + 1;
3767 }
3768
3769 return 0;
3770}
3771
3772static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3773{
3774 if (extension_is_supported (extname))
3775 if (set_reg8 (ctx, id, name, 0x01))
3776 return 1;
3777 return 0;
3778}
3779
3780/**
3781 * This kicks everything off.
3782 *
3783 * \param ctx - The GL Context
3784 * \param str - The program string
3785 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003786 * \param program - The arb_program struct to return all the parsed info in
3787 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003788 */
Brian Paul45703642005-10-29 15:52:31 +00003789GLboolean
Jouk Jansen40322e12004-04-05 08:50:36 +00003790_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3791 struct arb_program * program)
3792{
3793 GLint a, err, error_pos;
3794 char error_msg[300];
3795 GLuint parsed_len;
3796 struct var_cache *vc_head;
3797 grammar arbprogram_syn_id;
3798 GLubyte *parsed, *inst;
3799 GLubyte *strz = NULL;
3800 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3801
Brian Paul7f76b8f2004-09-10 01:05:39 +00003802 /* Reset error state */
3803 _mesa_set_program_error(ctx, -1, NULL);
3804
Jouk Jansen40322e12004-04-05 08:50:36 +00003805#if DEBUG_PARSING
3806 fprintf (stderr, "Loading grammar text!\n");
3807#endif
3808
3809 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3810 if (!arbprogram_syn_is_ok) {
3811 grammar grammar_syn_id;
3812 GLint err;
3813 GLuint parsed_len;
3814 byte *parsed;
3815
3816 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3817 if (grammar_syn_id == 0) {
3818 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3819 _mesa_set_program_error (ctx, error_pos, error_msg);
3820 _mesa_error (ctx, GL_INVALID_OPERATION,
3821 "Error loading grammar rule set");
Brian Paul45703642005-10-29 15:52:31 +00003822 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003823 }
3824
3825 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3826
Brian Paul45703642005-10-29 15:52:31 +00003827 /* NOTE: we can't destroy grammar_syn_id right here because
3828 * grammar_destroy() can reset the last error
3829 */
Jouk Jansen40322e12004-04-05 08:50:36 +00003830 if (err == 0) {
3831 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3832 _mesa_set_program_error (ctx, error_pos, error_msg);
3833 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3834
3835 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003836 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003837 }
3838
3839 grammar_destroy (grammar_syn_id);
3840
3841 arbprogram_syn_is_ok = 1;
3842 }
3843
3844 /* create the grammar object */
3845 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3846 if (arbprogram_syn_id == 0) {
3847 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3848 _mesa_set_program_error (ctx, error_pos, error_msg);
3849 _mesa_error (ctx, GL_INVALID_OPERATION,
3850 "Error loading grammer rule set");
Brian Paul45703642005-10-29 15:52:31 +00003851 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003852 }
3853
3854 /* Set program_target register value */
3855 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3856 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3857 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003858 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003859 }
3860
3861 /* Enable all active extensions */
3862 if (enable_ext (ctx, arbprogram_syn_id,
3863 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3864 enable_ext (ctx, arbprogram_syn_id,
3865 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
3866 enable_ext (ctx, arbprogram_syn_id,
3867 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
3868 enable_ext (ctx, arbprogram_syn_id,
3869 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
3870 enable_ext (ctx, arbprogram_syn_id,
3871 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
3872 enable_ext (ctx, arbprogram_syn_id,
3873 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
3874 enable_ext (ctx, arbprogram_syn_id,
3875 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
3876 enable_ext (ctx, arbprogram_syn_id,
Brian Pauledfe0fe2004-08-20 14:21:20 +00003877 (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
3878 enable_ext (ctx, arbprogram_syn_id,
Jouk Jansen40322e12004-04-05 08:50:36 +00003879 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
3880 enable_ext (ctx, arbprogram_syn_id,
3881 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
3882 enable_ext (ctx, arbprogram_syn_id,
Michal Krolad22ce82004-10-11 08:13:25 +00003883 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
3884 enable_ext (ctx, arbprogram_syn_id,
3885 (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003886 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003887 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003888 }
3889
3890 /* check for NULL character occurences */
3891 {
3892 int i;
3893 for (i = 0; i < len; i++)
3894 if (str[i] == '\0') {
3895 _mesa_set_program_error (ctx, i, "invalid character");
3896 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
3897
3898 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003899 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003900 }
3901 }
3902
3903 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003904 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003905 if (!strz) {
3906 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glprogramStringARB");
3907 return GL_FALSE;
3908 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003909 _mesa_memcpy (strz, str, len);
3910 strz[len] = '\0';
3911
3912#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003913 fprintf (stderr, "Checking Grammar!\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00003914#endif
Michal Krolb80bc052004-10-21 14:09:54 +00003915 /* do a fast check on program string - initial production buffer is 4K */
3916 err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00003917
3918 /* Syntax parse error */
3919 if (err == 0) {
3920 _mesa_free (strz);
3921 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3922 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul45703642005-10-29 15:52:31 +00003923 _mesa_error (ctx, GL_INVALID_OPERATION, "glprogramStringARB(syntax error)");
Brian Paul5fe90292004-07-20 21:15:13 +00003924
3925 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00003926#if DEBUG_PARSING
3927 do {
Brian Paul5fe90292004-07-20 21:15:13 +00003928 int line, col;
3929 char *s;
Brian Paul45703642005-10-29 15:52:31 +00003930 fprintf(stderr, "program: %s\n", (char *) strz);
3931 fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
3932 s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos, &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00003933 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
3934 } while (0)
3935#endif
Brian Paul5fe90292004-07-20 21:15:13 +00003936
Jouk Jansen40322e12004-04-05 08:50:36 +00003937 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003938 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003939 }
3940
3941#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003942 fprintf (stderr, "Destroying grammer dict [parse retval: %d]\n", err);
Jouk Jansen40322e12004-04-05 08:50:36 +00003943#endif
3944 grammar_destroy (arbprogram_syn_id);
3945
3946 /* Initialize the arb_program struct */
3947 program->Base.String = strz;
3948 program->Base.NumInstructions =
3949 program->Base.NumTemporaries =
3950 program->Base.NumParameters =
3951 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
3952 program->Parameters = _mesa_new_parameter_list ();
Brian Paul45cd2f92005-11-03 02:25:10 +00003953 program->InputsRead = 0x0;
3954 program->OutputsWritten = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003955 program->Position = 0;
3956 program->MajorVersion = program->MinorVersion = 0;
3957 program->PrecisionOption = GL_DONT_CARE;
3958 program->FogOption = GL_NONE;
3959 program->HintPositionInvariant = GL_FALSE;
3960 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
Brian Paul45cd2f92005-11-03 02:25:10 +00003961 program->TexturesUsed[a] = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003962 program->NumAluInstructions =
3963 program->NumTexInstructions =
3964 program->NumTexIndirections = 0;
3965
Keith Whitwellc3626a92005-11-01 17:25:49 +00003966 program->UsesKill = 0;
3967
Jouk Jansen40322e12004-04-05 08:50:36 +00003968 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00003969 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003970
3971 /* Start examining the tokens in the array */
3972 inst = parsed;
3973
3974 /* Check the grammer rev */
3975 if (*inst++ != REVISION) {
3976 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00003977 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul45cd2f92005-11-03 02:25:10 +00003978 "glProgramStringARB(Grammar version mismatch)");
Brian Paul45703642005-10-29 15:52:31 +00003979 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003980 }
3981 else {
Michal Krolb80bc052004-10-21 14:09:54 +00003982 /* ignore program target */
3983 inst++;
Jouk Jansen40322e12004-04-05 08:50:36 +00003984
3985 err = parse_arb_program (ctx, inst, &vc_head, program);
3986#if DEBUG_PARSING
3987 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
3988#endif
3989 }
3990
3991 /*debug_variables(ctx, vc_head, program); */
3992
3993 /* We're done with the parsed binary array */
3994 var_cache_destroy (&vc_head);
3995
3996 _mesa_free (parsed);
3997#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003998 fprintf (stderr, "_mesa_parse_arb_program() done\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00003999#endif
Brian Paul45703642005-10-29 15:52:31 +00004000
4001 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00004002}