blob: e1a42e2dd9d35390d3c78bf51c20761b28990f50 [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 Paulde997602005-11-12 17:53:14 +00001521 Program->Base.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 Paulde997602005-11-12 17:53:14 +00001612 Program->Base.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
Brian Paulde997602005-11-12 17:53:14 +00001701 idx = _mesa_add_state_reference(Program->Base.Parameters,
1702 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001703 if (param_var->param_binding_begin == ~0U)
1704 param_var->param_binding_begin = idx;
1705 param_var->param_binding_length++;
1706 Program->Base.NumParameters++;
1707 }
1708 }
1709 else {
Brian Paulde997602005-11-12 17:53:14 +00001710 idx = _mesa_add_state_reference(Program->Base.Parameters,
1711 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001712 if (param_var->param_binding_begin == ~0U)
1713 param_var->param_binding_begin = idx;
1714 param_var->param_binding_length++;
1715 Program->Base.NumParameters++;
1716 }
1717 break;
1718
1719 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001720 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1721 return 1;
Brian Paulde997602005-11-12 17:53:14 +00001722 idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001723 if (param_var->param_binding_begin == ~0U)
1724 param_var->param_binding_begin = idx;
1725 param_var->param_binding_length++;
1726 Program->Base.NumParameters++;
1727
1728 /* Check if there is more: 0 -> we're done, else its an integer */
1729 if (**inst) {
1730 GLuint out_of_range, new_idx;
1731 GLuint start_idx = state_tokens[2] + 1;
1732 GLuint end_idx = parse_integer (inst, Program);
1733
1734 out_of_range = 0;
1735 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1736 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001737 && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001738 || ((state_tokens[1] == STATE_LOCAL)
1739 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001740 ctx->Const.FragmentProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001741 out_of_range = 1;
1742 }
1743 else {
1744 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001745 && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001746 || ((state_tokens[1] == STATE_LOCAL)
1747 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001748 ctx->Const.VertexProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001749 out_of_range = 1;
1750 }
1751 if (out_of_range) {
1752 _mesa_set_program_error (ctx, Program->Position,
1753 "Invalid Program Parameter");
1754 _mesa_error (ctx, GL_INVALID_OPERATION,
1755 "Invalid Program Parameter: %d", end_idx);
1756 return 1;
1757 }
1758
1759 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1760 state_tokens[2] = new_idx;
Brian Paulde997602005-11-12 17:53:14 +00001761 idx = _mesa_add_state_reference(Program->Base.Parameters,
1762 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001763 param_var->param_binding_length++;
1764 Program->Base.NumParameters++;
1765 }
1766 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001767 else {
1768 (*inst)++;
1769 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001770 break;
1771
1772 case PARAM_CONSTANT:
1773 parse_constant (inst, const_values, Program, use);
Brian Paulde997602005-11-12 17:53:14 +00001774 idx = _mesa_add_named_constant(Program->Base.Parameters,
1775 (char *) param_var->name,
1776 const_values);
Jouk Jansen40322e12004-04-05 08:50:36 +00001777 if (param_var->param_binding_begin == ~0U)
1778 param_var->param_binding_begin = idx;
1779 param_var->param_binding_length++;
1780 Program->Base.NumParameters++;
1781 break;
1782
1783 default:
Brian Paul7aebaf32005-10-30 21:23:23 +00001784 _mesa_set_program_error(ctx, Program->Position,
1785 "Unexpected token in parse_param_elements()");
1786 _mesa_error(ctx, GL_INVALID_OPERATION,
1787 "Unexpected token in parse_param_elements()");
Jouk Jansen40322e12004-04-05 08:50:36 +00001788 return 1;
1789 }
1790
1791 /* Make sure we haven't blown past our parameter limits */
1792 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1793 (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001794 ctx->Const.VertexProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001795 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1796 && (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001797 ctx->Const.FragmentProgram.MaxLocalParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001798 _mesa_set_program_error (ctx, Program->Position,
1799 "Too many parameter variables");
1800 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1801 return 1;
1802 }
1803
1804 return err;
1805}
1806
Brian Paul7aebaf32005-10-30 21:23:23 +00001807
Jouk Jansen40322e12004-04-05 08:50:36 +00001808/**
1809 * This picks out PARAM program parameter bindings.
1810 *
1811 * XXX: This needs to be stressed & tested
1812 *
1813 * \return 0 on sucess, 1 on error
1814 */
1815static GLuint
1816parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1817 struct arb_program *Program)
1818{
Brian Paulbd997cd2004-07-20 21:12:56 +00001819 GLuint found, err;
1820 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001821 struct var_cache *param_var;
1822
1823 err = 0;
1824 param_var = parse_string (inst, vc_head, Program, &found);
1825 Program->Position = parse_position (inst);
1826
1827 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001828 char *error_msg = (char *)
1829 _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
Jouk Jansen40322e12004-04-05 08:50:36 +00001830 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1831 param_var->name);
1832
1833 _mesa_set_program_error (ctx, Program->Position, error_msg);
1834 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1835
1836 _mesa_free (error_msg);
1837 return 1;
1838 }
1839
1840 specified_length = parse_integer (inst, Program);
1841
1842 if (specified_length < 0) {
1843 _mesa_set_program_error (ctx, Program->Position,
1844 "Negative parameter array length");
1845 _mesa_error (ctx, GL_INVALID_OPERATION,
1846 "Negative parameter array length: %d", specified_length);
1847 return 1;
1848 }
1849
1850 param_var->type = vt_param;
1851 param_var->param_binding_length = 0;
1852
1853 /* Right now, everything is shoved into the main state register file.
1854 *
1855 * In the future, it would be nice to leave things ENV/LOCAL params
1856 * in their respective register files, if possible
1857 */
1858 param_var->param_binding_type = PROGRAM_STATE_VAR;
1859
1860 /* Remember to:
1861 * * - add each guy to the parameter list
1862 * * - increment the param_var->param_binding_len
1863 * * - store the param_var->param_binding_begin for the first one
1864 * * - compare the actual len to the specified len at the end
1865 */
1866 while (**inst != PARAM_NULL) {
1867 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1868 return 1;
1869 }
1870
1871 /* Test array length here! */
1872 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001873 if (specified_length != (int)param_var->param_binding_length) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001874 const char *msg
1875 = "Declared parameter array length does not match parameter list";
1876 _mesa_set_program_error(ctx, Program->Position, msg);
1877 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001878 }
1879 }
1880
1881 (*inst)++;
1882
1883 return 0;
1884}
1885
1886/**
1887 *
1888 */
1889static GLuint
1890parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1891 struct arb_program *Program, struct var_cache **new_var)
1892{
1893 struct var_cache *param_var;
1894
1895 /* First, insert a dummy entry into the var_cache */
1896 var_cache_create (&param_var);
1897 param_var->name = (GLubyte *) _mesa_strdup (" ");
1898 param_var->type = vt_param;
1899
1900 param_var->param_binding_length = 0;
1901 /* Don't fill in binding_begin; We use the default value of -1
1902 * to tell if its already initialized, elsewhere.
1903 *
1904 * param_var->param_binding_begin = 0;
1905 */
1906 param_var->param_binding_type = PROGRAM_STATE_VAR;
1907
1908 var_cache_append (vc_head, param_var);
1909
1910 /* Then fill it with juicy parameter goodness */
1911 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1912 return 1;
1913
1914 *new_var = param_var;
1915
1916 return 0;
1917}
1918
1919
1920/**
1921 * This handles the declaration of TEMP variables
1922 *
1923 * \return 0 on sucess, 1 on error
1924 */
1925static GLuint
1926parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1927 struct arb_program *Program)
1928{
1929 GLuint found;
1930 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00001931
1932 while (**inst != 0) {
1933 temp_var = parse_string (inst, vc_head, Program, &found);
1934 Program->Position = parse_position (inst);
1935 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001936 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001937 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
1938 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1939 temp_var->name);
1940
1941 _mesa_set_program_error (ctx, Program->Position, error_msg);
1942 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1943
1944 _mesa_free (error_msg);
1945 return 1;
1946 }
1947
1948 temp_var->type = vt_temp;
1949
1950 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1951 (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001952 ctx->Const.FragmentProgram.MaxTemps))
Jouk Jansen40322e12004-04-05 08:50:36 +00001953 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
1954 && (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001955 ctx->Const.VertexProgram.MaxTemps))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001956 _mesa_set_program_error (ctx, Program->Position,
1957 "Too many TEMP variables declared");
1958 _mesa_error (ctx, GL_INVALID_OPERATION,
1959 "Too many TEMP variables declared");
1960 return 1;
1961 }
1962
1963 temp_var->temp_binding = Program->Base.NumTemporaries;
1964 Program->Base.NumTemporaries++;
1965 }
1966 (*inst)++;
1967
1968 return 0;
1969}
1970
1971/**
1972 * This handles variables of the OUTPUT variety
1973 *
1974 * \return 0 on sucess, 1 on error
1975 */
1976static GLuint
1977parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1978 struct arb_program *Program)
1979{
1980 GLuint found;
1981 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00001982 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00001983
1984 output_var = parse_string (inst, vc_head, Program, &found);
1985 Program->Position = parse_position (inst);
1986 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001987 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001988 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
1989 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1990 output_var->name);
1991
1992 _mesa_set_program_error (ctx, Program->Position, error_msg);
1993 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1994
1995 _mesa_free (error_msg);
1996 return 1;
1997 }
1998
1999 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002000
2001 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2002 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002003}
2004
2005/**
2006 * This handles variables of the ALIAS kind
2007 *
2008 * \return 0 on sucess, 1 on error
2009 */
2010static GLuint
2011parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2012 struct arb_program *Program)
2013{
2014 GLuint found;
2015 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002016
2017 temp_var = parse_string (inst, vc_head, Program, &found);
2018 Program->Position = parse_position (inst);
2019
2020 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002021 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002022 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2023 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2024 temp_var->name);
2025
2026 _mesa_set_program_error (ctx, Program->Position, error_msg);
2027 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2028
2029 _mesa_free (error_msg);
2030 return 1;
2031 }
2032
2033 temp_var->type = vt_alias;
2034 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2035 Program->Position = parse_position (inst);
2036
2037 if (!found)
2038 {
Brian Paul7aebaf32005-10-30 21:23:23 +00002039 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002040 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2041 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2042 temp_var->alias_binding->name);
2043
2044 _mesa_set_program_error (ctx, Program->Position, error_msg);
2045 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2046
2047 _mesa_free (error_msg);
2048 return 1;
2049 }
2050
2051 return 0;
2052}
2053
2054/**
2055 * This handles variables of the ADDRESS kind
2056 *
2057 * \return 0 on sucess, 1 on error
2058 */
2059static GLuint
2060parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2061 struct arb_program *Program)
2062{
2063 GLuint found;
2064 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002065
2066 while (**inst != 0) {
2067 temp_var = parse_string (inst, vc_head, Program, &found);
2068 Program->Position = parse_position (inst);
2069 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002070 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002071 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2072 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2073 temp_var->name);
2074
2075 _mesa_set_program_error (ctx, Program->Position, error_msg);
2076 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2077
2078 _mesa_free (error_msg);
2079 return 1;
2080 }
2081
2082 temp_var->type = vt_address;
2083
2084 if (Program->Base.NumAddressRegs >=
Brian Paul05051032005-11-01 04:36:33 +00002085 ctx->Const.VertexProgram.MaxAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002086 const char *msg = "Too many ADDRESS variables declared";
2087 _mesa_set_program_error(ctx, Program->Position, msg);
2088
2089 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002090 return 1;
2091 }
2092
2093 temp_var->address_binding = Program->Base.NumAddressRegs;
2094 Program->Base.NumAddressRegs++;
2095 }
2096 (*inst)++;
2097
2098 return 0;
2099}
2100
2101/**
2102 * Parse a program declaration
2103 *
2104 * \return 0 on sucess, 1 on error
2105 */
2106static GLint
2107parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2108 struct arb_program *Program)
2109{
2110 GLint err = 0;
2111
2112 switch (*(*inst)++) {
2113 case ADDRESS:
2114 err = parse_address (ctx, inst, vc_head, Program);
2115 break;
2116
2117 case ALIAS:
2118 err = parse_alias (ctx, inst, vc_head, Program);
2119 break;
2120
2121 case ATTRIB:
2122 err = parse_attrib (ctx, inst, vc_head, Program);
2123 break;
2124
2125 case OUTPUT:
2126 err = parse_output (ctx, inst, vc_head, Program);
2127 break;
2128
2129 case PARAM:
2130 err = parse_param (ctx, inst, vc_head, Program);
2131 break;
2132
2133 case TEMP:
2134 err = parse_temp (ctx, inst, vc_head, Program);
2135 break;
2136 }
2137
2138 return err;
2139}
2140
2141/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002142 * Handle the parsing out of a masked destination register, either for a
2143 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002144 *
2145 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002146 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002147 * position invariant
2148 *
2149 * \param File - The register file we write to
2150 * \param Index - The register index we write to
2151 * \param WriteMask - The mask controlling which components we write (1->write)
2152 *
2153 * \return 0 on sucess, 1 on error
2154 */
2155static GLuint
2156parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2157 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002158 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002159{
Brian Paul7aebaf32005-10-30 21:23:23 +00002160 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002161 struct var_cache *dst;
2162
2163 /* We either have a result register specified, or a
2164 * variable that may or may not be writable
2165 */
2166 switch (*(*inst)++) {
2167 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002168 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002169 return 1;
2170 *File = PROGRAM_OUTPUT;
2171 break;
2172
2173 case REGISTER_ESTABLISHED_NAME:
2174 dst = parse_string (inst, vc_head, Program, &result);
2175 Program->Position = parse_position (inst);
2176
2177 /* If the name has never been added to our symbol table, we're hosed */
2178 if (!result) {
2179 _mesa_set_program_error (ctx, Program->Position,
2180 "0: Undefined variable");
2181 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2182 dst->name);
2183 return 1;
2184 }
2185
2186 switch (dst->type) {
2187 case vt_output:
2188 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002189 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002190 break;
2191
2192 case vt_temp:
2193 *File = PROGRAM_TEMPORARY;
2194 *Index = dst->temp_binding;
2195 break;
2196
2197 /* If the var type is not vt_output or vt_temp, no go */
2198 default:
2199 _mesa_set_program_error (ctx, Program->Position,
2200 "Destination register is read only");
2201 _mesa_error (ctx, GL_INVALID_OPERATION,
2202 "Destination register is read only: %s",
2203 dst->name);
2204 return 1;
2205 }
2206 break;
2207
2208 default:
2209 _mesa_set_program_error (ctx, Program->Position,
2210 "Unexpected opcode in parse_masked_dst_reg()");
2211 _mesa_error (ctx, GL_INVALID_OPERATION,
2212 "Unexpected opcode in parse_masked_dst_reg()");
2213 return 1;
2214 }
2215
2216
2217 /* Position invariance test */
2218 /* This test is done now in syntax portion - when position invariance OPTION
2219 is specified, "result.position" rule is disabled so there is no way
2220 to write the position
2221 */
2222 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2223 (*Index == 0)) {
2224 _mesa_set_program_error (ctx, Program->Position,
2225 "Vertex program specified position invariance and wrote vertex position");
2226 _mesa_error (ctx, GL_INVALID_OPERATION,
2227 "Vertex program specified position invariance and wrote vertex position");
2228 }*/
2229
2230 /* And then the mask.
2231 * w,a -> bit 0
2232 * z,b -> bit 1
2233 * y,g -> bit 2
2234 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002235 *
2236 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002237 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002238 tmp = (GLint) *(*inst)++;
2239 *WriteMask = (((tmp>>3) & 0x1) |
2240 ((tmp>>1) & 0x2) |
2241 ((tmp<<1) & 0x4) |
2242 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002243
2244 return 0;
2245}
2246
2247
2248/**
2249 * Handle the parsing of a address register
2250 *
2251 * \param Index - The register index we write to
2252 *
2253 * \return 0 on sucess, 1 on error
2254 */
2255static GLuint
2256parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2257 struct var_cache **vc_head,
2258 struct arb_program *Program, GLint * Index)
2259{
2260 struct var_cache *dst;
2261 GLuint result;
Brian Paula6c423d2004-08-25 15:59:48 +00002262 (void) Index;
Jouk Jansen40322e12004-04-05 08:50:36 +00002263
2264 dst = parse_string (inst, vc_head, Program, &result);
2265 Program->Position = parse_position (inst);
2266
2267 /* If the name has never been added to our symbol table, we're hosed */
2268 if (!result) {
2269 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2270 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2271 dst->name);
2272 return 1;
2273 }
2274
2275 if (dst->type != vt_address) {
2276 _mesa_set_program_error (ctx, Program->Position,
2277 "Variable is not of type ADDRESS");
2278 _mesa_error (ctx, GL_INVALID_OPERATION,
2279 "Variable: %s is not of type ADDRESS", dst->name);
2280 return 1;
2281 }
2282
2283 return 0;
2284}
2285
Brian Paul8e8fa632005-07-01 02:03:33 +00002286#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002287/**
2288 * Handle the parsing out of a masked address register
2289 *
2290 * \param Index - The register index we write to
2291 * \param WriteMask - The mask controlling which components we write (1->write)
2292 *
2293 * \return 0 on sucess, 1 on error
2294 */
2295static GLuint
2296parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2297 struct var_cache **vc_head,
2298 struct arb_program *Program, GLint * Index,
2299 GLboolean * WriteMask)
2300{
2301 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2302 return 1;
2303
2304 /* This should be 0x8 */
2305 (*inst)++;
2306
2307 /* Writemask of .x is implied */
2308 WriteMask[0] = 1;
2309 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2310
2311 return 0;
2312}
Brian Paul8e8fa632005-07-01 02:03:33 +00002313#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002314
2315/**
2316 * Parse out a swizzle mask.
2317 *
Brian Paul32df89e2005-10-29 18:26:43 +00002318 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002319 *
2320 * The len parameter allows us to grab 4 components for a vector
2321 * swizzle, or just 1 component for a scalar src register selection
2322 */
Brian Paul32df89e2005-10-29 18:26:43 +00002323static void
2324parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002325{
Brian Paul32df89e2005-10-29 18:26:43 +00002326 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002327
Brian Paul32df89e2005-10-29 18:26:43 +00002328 for (i = 0; i < 4; i++)
2329 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002330
Brian Paul32df89e2005-10-29 18:26:43 +00002331 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002332 switch (*(*inst)++) {
2333 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002334 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002335 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002336 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002337 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002338 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002339 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002340 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002341 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002342 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002343 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002344 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002345 default:
2346 _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
2347 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002348 }
2349 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002350}
2351
Jouk Jansen40322e12004-04-05 08:50:36 +00002352
Brian Paul32df89e2005-10-29 18:26:43 +00002353/**
2354 * Parse an extended swizzle mask which is a sequence of
2355 * four x/y/z/w/0/1 tokens.
2356 * \return swizzle four swizzle values
2357 * \return negateMask four element bitfield
2358 */
2359static void
2360parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4],
2361 GLubyte *negateMask)
2362{
2363 GLint i;
2364
2365 *negateMask = 0x0;
2366 for (i = 0; i < 4; i++) {
2367 GLubyte swz;
2368 if (parse_sign(inst) == -1)
2369 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002370
2371 swz = *(*inst)++;
2372
2373 switch (swz) {
2374 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002375 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002376 break;
2377 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002378 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002379 break;
2380 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002381 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002382 break;
2383 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002384 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002385 break;
2386 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002387 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002388 break;
2389 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002390 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002391 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002392 default:
2393 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2394 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002395 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002396 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002397}
2398
2399
2400static GLuint
2401parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002402 struct arb_program *Program,
2403 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002404 GLboolean *IsRelOffset )
2405{
2406 struct var_cache *src;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002407 GLuint binding, is_generic, found;
Brian Paulbd997cd2004-07-20 21:12:56 +00002408 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002409
Keith Whitwell7c26b612005-04-21 14:46:57 +00002410 *IsRelOffset = 0;
2411
Jouk Jansen40322e12004-04-05 08:50:36 +00002412 /* And the binding for the src */
2413 switch (*(*inst)++) {
2414 case REGISTER_ATTRIB:
2415 if (parse_attrib_binding
Brian Paul18e7c5c2005-10-30 21:46:00 +00002416 (ctx, inst, Program, &binding, &is_generic))
Jouk Jansen40322e12004-04-05 08:50:36 +00002417 return 1;
2418 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002419 *Index = binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002420
2421 /* We need to insert a dummy variable into the var_cache so we can
2422 * catch generic vertex attrib aliasing errors
2423 */
2424 var_cache_create(&src);
2425 src->type = vt_attrib;
2426 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
Brian Paul18e7c5c2005-10-30 21:46:00 +00002427 src->attrib_binding = binding;
2428 src->attrib_is_generic = is_generic;
Jouk Jansen40322e12004-04-05 08:50:36 +00002429 var_cache_append(vc_head, src);
2430 if (generic_attrib_check(*vc_head)) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002431 const char *msg = "Cannot use both a generic vertex attribute "
2432 "and a specific attribute of the same type";
2433 _mesa_set_program_error (ctx, Program->Position, msg);
2434 _mesa_error (ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002435 return 1;
2436 }
2437 break;
2438
2439 case REGISTER_PARAM:
2440 switch (**inst) {
2441 case PARAM_ARRAY_ELEMENT:
2442 (*inst)++;
2443 src = parse_string (inst, vc_head, Program, &found);
2444 Program->Position = parse_position (inst);
2445
2446 if (!found) {
2447 _mesa_set_program_error (ctx, Program->Position,
2448 "2: Undefined variable");
2449 _mesa_error (ctx, GL_INVALID_OPERATION,
2450 "2: Undefined variable: %s", src->name);
2451 return 1;
2452 }
2453
2454 *File = src->param_binding_type;
2455
2456 switch (*(*inst)++) {
2457 case ARRAY_INDEX_ABSOLUTE:
2458 offset = parse_integer (inst, Program);
2459
2460 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002461 || (offset >= (int)src->param_binding_length)) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002462 _mesa_set_program_error (ctx, Program->Position,
2463 "Index out of range");
2464 _mesa_error (ctx, GL_INVALID_OPERATION,
2465 "Index %d out of range for %s", offset,
2466 src->name);
2467 return 1;
2468 }
2469
2470 *Index = src->param_binding_begin + offset;
2471 break;
2472
2473 case ARRAY_INDEX_RELATIVE:
2474 {
2475 GLint addr_reg_idx, rel_off;
2476
2477 /* First, grab the address regiseter */
2478 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2479 return 1;
2480
2481 /* And the .x */
2482 ((*inst)++);
2483 ((*inst)++);
2484 ((*inst)++);
2485 ((*inst)++);
2486
2487 /* Then the relative offset */
2488 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2489
2490 /* And store it properly */
2491 *Index = src->param_binding_begin + rel_off;
2492 *IsRelOffset = 1;
2493 }
2494 break;
2495 }
2496 break;
2497
2498 default:
Jouk Jansen40322e12004-04-05 08:50:36 +00002499 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2500 return 1;
2501
2502 *File = src->param_binding_type;
2503 *Index = src->param_binding_begin;
2504 break;
2505 }
2506 break;
2507
2508 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002509 src = parse_string (inst, vc_head, Program, &found);
2510 Program->Position = parse_position (inst);
2511
2512 /* If the name has never been added to our symbol table, we're hosed */
2513 if (!found) {
2514 _mesa_set_program_error (ctx, Program->Position,
2515 "3: Undefined variable");
2516 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2517 src->name);
2518 return 1;
2519 }
2520
2521 switch (src->type) {
2522 case vt_attrib:
2523 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002524 *Index = src->attrib_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002525 break;
2526
2527 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2528 case vt_param:
2529 *File = src->param_binding_type;
2530 *Index = src->param_binding_begin;
2531 break;
2532
2533 case vt_temp:
2534 *File = PROGRAM_TEMPORARY;
2535 *Index = src->temp_binding;
2536 break;
2537
2538 /* If the var type is vt_output no go */
2539 default:
2540 _mesa_set_program_error (ctx, Program->Position,
2541 "destination register is read only");
2542 _mesa_error (ctx, GL_INVALID_OPERATION,
2543 "destination register is read only: %s",
2544 src->name);
2545 return 1;
2546 }
2547 break;
2548
2549 default:
2550 _mesa_set_program_error (ctx, Program->Position,
2551 "Unknown token in parse_src_reg");
2552 _mesa_error (ctx, GL_INVALID_OPERATION,
2553 "Unknown token in parse_src_reg");
2554 return 1;
2555 }
2556
2557 return 0;
2558}
2559
2560/**
Brian Paul18e7c5c2005-10-30 21:46:00 +00002561 * Parse fragment program vector source register.
Jouk Jansen40322e12004-04-05 08:50:36 +00002562 */
2563static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00002564parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
2565 struct var_cache **vc_head,
2566 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00002567 struct prog_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002568{
Brian Paul7aebaf32005-10-30 21:23:23 +00002569 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002570 GLint index;
2571 GLboolean negate;
2572 GLubyte swizzle[4];
2573 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002574
Jouk Jansen40322e12004-04-05 08:50:36 +00002575 /* Grab the sign */
Brian Paul32df89e2005-10-29 18:26:43 +00002576 negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002577
2578 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002579 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002580 return 1;
2581
2582 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002583 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002584
Brian Paul32df89e2005-10-29 18:26:43 +00002585 reg->File = file;
2586 reg->Index = index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002587 reg->Abs = 0; /* NV only */
2588 reg->NegateAbs = 0; /* NV only */
Brian Paul32df89e2005-10-29 18:26:43 +00002589 reg->NegateBase = negate;
2590 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00002591 return 0;
2592}
2593
Jouk Jansen40322e12004-04-05 08:50:36 +00002594
Keith Whitwell7c26b612005-04-21 14:46:57 +00002595static GLuint
2596parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
2597 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002598 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002599{
Brian Paul7aebaf32005-10-30 21:23:23 +00002600 GLint mask;
2601 GLuint idx;
2602 enum register_file file;
2603
Keith Whitwell7c26b612005-04-21 14:46:57 +00002604 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002605 return 1;
2606
Keith Whitwell7c26b612005-04-21 14:46:57 +00002607 reg->CondMask = 0; /* NV only */
2608 reg->CondSwizzle = 0; /* NV only */
2609 reg->File = file;
2610 reg->Index = idx;
2611 reg->WriteMask = mask;
2612 return 0;
2613}
2614
2615
Brian Paul7aebaf32005-10-30 21:23:23 +00002616/**
2617 * Parse fragment program scalar src register.
2618 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002619static GLuint
2620parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00002621 struct var_cache **vc_head,
2622 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002623 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002624{
Brian Paul7aebaf32005-10-30 21:23:23 +00002625 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002626 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00002627 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002628 GLubyte Swizzle[4];
2629 GLboolean IsRelOffset;
2630
2631 /* Grab the sign */
2632 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2633
2634 /* And the src reg */
2635 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2636 return 1;
2637
2638 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002639 parse_swizzle_mask(inst, Swizzle, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002640
Keith Whitwell7c26b612005-04-21 14:46:57 +00002641 reg->File = File;
2642 reg->Index = Index;
2643 reg->Abs = 0; /* NV only */
2644 reg->NegateAbs = 0; /* NV only */
2645 reg->NegateBase = Negate;
2646 reg->Swizzle = (Swizzle[0] << 0);
2647
Jouk Jansen40322e12004-04-05 08:50:36 +00002648 return 0;
2649}
2650
Keith Whitwell7c26b612005-04-21 14:46:57 +00002651
Jouk Jansen40322e12004-04-05 08:50:36 +00002652/**
2653 * This is a big mother that handles getting opcodes into the instruction
2654 * and handling the src & dst registers for fragment program instructions
2655 */
2656static GLuint
2657parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2658 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002659 struct prog_instruction *fp)
Jouk Jansen40322e12004-04-05 08:50:36 +00002660{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002661 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002662 GLuint texcoord;
2663 GLubyte instClass, type, code;
2664 GLboolean rel;
2665
Brian Paul7e807512005-11-05 17:10:45 +00002666 _mesa_init_instruction(fp);
Jouk Jansen40322e12004-04-05 08:50:36 +00002667
2668 /* Record the position in the program string for debugging */
2669 fp->StringPos = Program->Position;
2670
2671 /* OP_ALU_INST or OP_TEX_INST */
2672 instClass = *(*inst)++;
2673
2674 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2675 * OP_TEX_{SAMPLE, KIL}
2676 */
2677 type = *(*inst)++;
2678
2679 /* The actual opcode name */
2680 code = *(*inst)++;
2681
2682 /* Increment the correct count */
2683 switch (instClass) {
2684 case OP_ALU_INST:
2685 Program->NumAluInstructions++;
2686 break;
2687 case OP_TEX_INST:
2688 Program->NumTexInstructions++;
2689 break;
2690 }
2691
Jouk Jansen40322e12004-04-05 08:50:36 +00002692 switch (type) {
2693 case OP_ALU_VECTOR:
2694 switch (code) {
2695 case OP_ABS_SAT:
2696 fp->Saturate = 1;
2697 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00002698 fp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002699 break;
2700
2701 case OP_FLR_SAT:
2702 fp->Saturate = 1;
2703 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00002704 fp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00002705 break;
2706
2707 case OP_FRC_SAT:
2708 fp->Saturate = 1;
2709 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00002710 fp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00002711 break;
2712
2713 case OP_LIT_SAT:
2714 fp->Saturate = 1;
2715 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00002716 fp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002717 break;
2718
2719 case OP_MOV_SAT:
2720 fp->Saturate = 1;
2721 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00002722 fp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00002723 break;
2724 }
2725
Keith Whitwell7c26b612005-04-21 14:46:57 +00002726 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002727 return 1;
2728
Keith Whitwell7c26b612005-04-21 14:46:57 +00002729 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002730 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002731 break;
2732
2733 case OP_ALU_SCALAR:
2734 switch (code) {
2735 case OP_COS_SAT:
2736 fp->Saturate = 1;
2737 case OP_COS:
Brian Paul7e807512005-11-05 17:10:45 +00002738 fp->Opcode = OPCODE_COS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002739 break;
2740
2741 case OP_EX2_SAT:
2742 fp->Saturate = 1;
2743 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00002744 fp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002745 break;
2746
2747 case OP_LG2_SAT:
2748 fp->Saturate = 1;
2749 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00002750 fp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002751 break;
2752
2753 case OP_RCP_SAT:
2754 fp->Saturate = 1;
2755 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00002756 fp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002757 break;
2758
2759 case OP_RSQ_SAT:
2760 fp->Saturate = 1;
2761 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00002762 fp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002763 break;
2764
2765 case OP_SIN_SAT:
2766 fp->Saturate = 1;
2767 case OP_SIN:
Brian Paul7e807512005-11-05 17:10:45 +00002768 fp->Opcode = OPCODE_SIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002769 break;
2770
2771 case OP_SCS_SAT:
2772 fp->Saturate = 1;
2773 case OP_SCS:
2774
Brian Paul7e807512005-11-05 17:10:45 +00002775 fp->Opcode = OPCODE_SCS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002776 break;
2777 }
2778
Keith Whitwell7c26b612005-04-21 14:46:57 +00002779 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002780 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002781
2782 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002783 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002784 break;
2785
2786 case OP_ALU_BINSC:
2787 switch (code) {
2788 case OP_POW_SAT:
2789 fp->Saturate = 1;
2790 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00002791 fp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00002792 break;
2793 }
2794
Keith Whitwell7c26b612005-04-21 14:46:57 +00002795 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002796 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002797
Jouk Jansen40322e12004-04-05 08:50:36 +00002798 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002799 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002800 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002801 }
2802 break;
2803
2804
2805 case OP_ALU_BIN:
2806 switch (code) {
2807 case OP_ADD_SAT:
2808 fp->Saturate = 1;
2809 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00002810 fp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002811 break;
2812
2813 case OP_DP3_SAT:
2814 fp->Saturate = 1;
2815 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00002816 fp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00002817 break;
2818
2819 case OP_DP4_SAT:
2820 fp->Saturate = 1;
2821 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00002822 fp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00002823 break;
2824
2825 case OP_DPH_SAT:
2826 fp->Saturate = 1;
2827 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00002828 fp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00002829 break;
2830
2831 case OP_DST_SAT:
2832 fp->Saturate = 1;
2833 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00002834 fp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00002835 break;
2836
2837 case OP_MAX_SAT:
2838 fp->Saturate = 1;
2839 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00002840 fp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002841 break;
2842
2843 case OP_MIN_SAT:
2844 fp->Saturate = 1;
2845 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00002846 fp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002847 break;
2848
2849 case OP_MUL_SAT:
2850 fp->Saturate = 1;
2851 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00002852 fp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00002853 break;
2854
2855 case OP_SGE_SAT:
2856 fp->Saturate = 1;
2857 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00002858 fp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002859 break;
2860
2861 case OP_SLT_SAT:
2862 fp->Saturate = 1;
2863 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00002864 fp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002865 break;
2866
2867 case OP_SUB_SAT:
2868 fp->Saturate = 1;
2869 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00002870 fp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002871 break;
2872
2873 case OP_XPD_SAT:
2874 fp->Saturate = 1;
2875 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00002876 fp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002877 break;
2878 }
2879
Keith Whitwell7c26b612005-04-21 14:46:57 +00002880 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002881 return 1;
2882 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002883 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2884 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002885 }
2886 break;
2887
2888 case OP_ALU_TRI:
2889 switch (code) {
2890 case OP_CMP_SAT:
2891 fp->Saturate = 1;
2892 case OP_CMP:
Brian Paul7e807512005-11-05 17:10:45 +00002893 fp->Opcode = OPCODE_CMP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002894 break;
2895
2896 case OP_LRP_SAT:
2897 fp->Saturate = 1;
2898 case OP_LRP:
Brian Paul7e807512005-11-05 17:10:45 +00002899 fp->Opcode = OPCODE_LRP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002900 break;
2901
2902 case OP_MAD_SAT:
2903 fp->Saturate = 1;
2904 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00002905 fp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002906 break;
2907 }
2908
Keith Whitwell7c26b612005-04-21 14:46:57 +00002909 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002910 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002911
Jouk Jansen40322e12004-04-05 08:50:36 +00002912 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002913 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2914 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002915 }
2916 break;
2917
2918 case OP_ALU_SWZ:
2919 switch (code) {
2920 case OP_SWZ_SAT:
2921 fp->Saturate = 1;
2922 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00002923 fp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002924 break;
2925 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00002926 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002927 return 1;
2928
Keith Whitwell7c26b612005-04-21 14:46:57 +00002929 {
Brian Paul32df89e2005-10-29 18:26:43 +00002930 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002931 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002932 enum register_file file;
2933 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002934
Brian Paul32df89e2005-10-29 18:26:43 +00002935 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002936 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00002937 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
2938 fp->SrcReg[0].File = file;
2939 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00002940 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002941 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
2942 swizzle[1],
2943 swizzle[2],
2944 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00002945 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002946 break;
2947
2948 case OP_TEX_SAMPLE:
2949 switch (code) {
2950 case OP_TEX_SAT:
2951 fp->Saturate = 1;
2952 case OP_TEX:
Brian Paul7e807512005-11-05 17:10:45 +00002953 fp->Opcode = OPCODE_TEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002954 break;
2955
2956 case OP_TXP_SAT:
2957 fp->Saturate = 1;
2958 case OP_TXP:
Brian Paul7e807512005-11-05 17:10:45 +00002959 fp->Opcode = OPCODE_TXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002960 break;
2961
2962 case OP_TXB_SAT:
Jouk Jansen40322e12004-04-05 08:50:36 +00002963 fp->Saturate = 1;
2964 case OP_TXB:
Brian Paul7e807512005-11-05 17:10:45 +00002965 fp->Opcode = OPCODE_TXB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002966 break;
2967 }
2968
Keith Whitwell7c26b612005-04-21 14:46:57 +00002969 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002970 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002971
2972 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002973 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002974
2975 /* texImageUnit */
2976 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
2977 return 1;
2978 fp->TexSrcUnit = texcoord;
2979
2980 /* texTarget */
2981 switch (*(*inst)++) {
2982 case TEXTARGET_1D:
Brian Paul7e807512005-11-05 17:10:45 +00002983 fp->TexSrcTarget = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002984 break;
2985 case TEXTARGET_2D:
Brian Paul7e807512005-11-05 17:10:45 +00002986 fp->TexSrcTarget = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002987 break;
2988 case TEXTARGET_3D:
Brian Paul7e807512005-11-05 17:10:45 +00002989 fp->TexSrcTarget = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002990 break;
2991 case TEXTARGET_RECT:
Brian Paul7e807512005-11-05 17:10:45 +00002992 fp->TexSrcTarget = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002993 break;
2994 case TEXTARGET_CUBE:
Brian Paul7e807512005-11-05 17:10:45 +00002995 fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002996 break;
2997 case TEXTARGET_SHADOW1D:
2998 case TEXTARGET_SHADOW2D:
2999 case TEXTARGET_SHADOWRECT:
3000 /* TODO ARB_fragment_program_shadow code */
3001 break;
3002 }
Brian Paul7e807512005-11-05 17:10:45 +00003003 Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcTarget);
Jouk Jansen40322e12004-04-05 08:50:36 +00003004 break;
3005
3006 case OP_TEX_KIL:
Keith Whitwellc3626a92005-11-01 17:25:49 +00003007 Program->UsesKill = 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003008 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003009 return 1;
Brian Paul7e807512005-11-05 17:10:45 +00003010 fp->Opcode = OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003011 break;
3012 }
3013
3014 return 0;
3015}
3016
Keith Whitwell7c26b612005-04-21 14:46:57 +00003017static GLuint
3018parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
3019 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003020 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003021{
Brian Paul7aebaf32005-10-30 21:23:23 +00003022 GLint mask;
3023 GLuint idx;
3024 enum register_file file;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003025
3026 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3027 return 1;
3028
3029 reg->File = file;
3030 reg->Index = idx;
3031 reg->WriteMask = mask;
3032 return 0;
3033}
3034
3035/**
3036 * Handle the parsing out of a masked address register
3037 *
3038 * \param Index - The register index we write to
3039 * \param WriteMask - The mask controlling which components we write (1->write)
3040 *
3041 * \return 0 on sucess, 1 on error
3042 */
3043static GLuint
3044parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
3045 struct var_cache **vc_head,
3046 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003047 struct prog_dst_register *reg)
Keith Whitwell7c26b612005-04-21 14:46:57 +00003048{
3049 GLint idx;
3050
3051 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3052 return 1;
3053
3054 /* This should be 0x8 */
3055 (*inst)++;
3056
3057 reg->File = PROGRAM_ADDRESS;
3058 reg->Index = idx;
3059
3060 /* Writemask of .x is implied */
3061 reg->WriteMask = 0x1;
3062 return 0;
3063}
3064
3065/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003066 * Parse vertex program vector source register.
Keith Whitwell7c26b612005-04-21 14:46:57 +00003067 */
3068static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00003069parse_vp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
3070 struct var_cache **vc_head,
3071 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00003072 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003073{
Brian Paul7aebaf32005-10-30 21:23:23 +00003074 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00003075 GLint index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003076 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003077 GLubyte swizzle[4];
3078 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003079
3080 /* Grab the sign */
Brian Paul7aebaf32005-10-30 21:23:23 +00003081 negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003082
3083 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00003084 if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003085 return 1;
3086
3087 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003088 parse_swizzle_mask(inst, swizzle, 4);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003089
Brian Paul32df89e2005-10-29 18:26:43 +00003090 reg->File = file;
3091 reg->Index = index;
3092 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
3093 swizzle[2], swizzle[3]);
Brian Paul7e807512005-11-05 17:10:45 +00003094 reg->NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003095 reg->RelAddr = isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003096 return 0;
3097}
3098
3099
3100static GLuint
3101parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00003102 struct var_cache **vc_head,
3103 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003104 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003105{
Brian Paul7aebaf32005-10-30 21:23:23 +00003106 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003107 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003108 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003109 GLubyte Swizzle[4];
3110 GLboolean IsRelOffset;
3111
3112 /* Grab the sign */
3113 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3114
3115 /* And the src reg */
3116 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3117 return 1;
3118
3119 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003120 parse_swizzle_mask(inst, Swizzle, 1);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003121
3122 reg->File = File;
3123 reg->Index = Index;
3124 reg->Swizzle = (Swizzle[0] << 0);
Brian Paul7e807512005-11-05 17:10:45 +00003125 reg->NegateBase = Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003126 reg->RelAddr = IsRelOffset;
3127 return 0;
3128}
3129
3130
Jouk Jansen40322e12004-04-05 08:50:36 +00003131/**
3132 * This is a big mother that handles getting opcodes into the instruction
3133 * and handling the src & dst registers for vertex program instructions
3134 */
3135static GLuint
3136parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3137 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003138 struct prog_instruction *vp)
Jouk Jansen40322e12004-04-05 08:50:36 +00003139{
3140 GLint a;
3141 GLubyte type, code;
3142
3143 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3144 type = *(*inst)++;
3145
3146 /* The actual opcode name */
3147 code = *(*inst)++;
3148
Brian Paul7e807512005-11-05 17:10:45 +00003149 _mesa_init_instruction(vp);
Jouk Jansen40322e12004-04-05 08:50:36 +00003150 /* Record the position in the program string for debugging */
3151 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003152
3153 switch (type) {
3154 /* XXX: */
3155 case OP_ALU_ARL:
Brian Paul7e807512005-11-05 17:10:45 +00003156 vp->Opcode = OPCODE_ARL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003157
3158 /* Remember to set SrcReg.RelAddr; */
3159
3160 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003161 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003162 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003163
Jouk Jansen40322e12004-04-05 08:50:36 +00003164 vp->DstReg.File = PROGRAM_ADDRESS;
3165
3166 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003167 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003168 return 1;
3169
3170 break;
3171
3172 case OP_ALU_VECTOR:
3173 switch (code) {
3174 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00003175 vp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00003176 break;
3177 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00003178 vp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00003179 break;
3180 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00003181 vp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00003182 break;
3183 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00003184 vp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003185 break;
3186 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00003187 vp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00003188 break;
3189 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003190
3191 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003192 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003193
3194 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003195 return 1;
3196 break;
3197
3198 case OP_ALU_SCALAR:
3199 switch (code) {
3200 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00003201 vp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003202 break;
3203 case OP_EXP:
Brian Paul7e807512005-11-05 17:10:45 +00003204 vp->Opcode = OPCODE_EXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003205 break;
3206 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00003207 vp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003208 break;
3209 case OP_LOG:
Brian Paul7e807512005-11-05 17:10:45 +00003210 vp->Opcode = OPCODE_LOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00003211 break;
3212 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00003213 vp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003214 break;
3215 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00003216 vp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003217 break;
3218 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003219 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003220 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003221
3222 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003223 return 1;
3224 break;
3225
3226 case OP_ALU_BINSC:
3227 switch (code) {
3228 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00003229 vp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00003230 break;
3231 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003232 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003233 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003234
Jouk Jansen40322e12004-04-05 08:50:36 +00003235 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003236 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003237 return 1;
3238 }
3239 break;
3240
3241 case OP_ALU_BIN:
3242 switch (code) {
3243 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00003244 vp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003245 break;
3246 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00003247 vp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00003248 break;
3249 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00003250 vp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00003251 break;
3252 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00003253 vp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00003254 break;
3255 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00003256 vp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00003257 break;
3258 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00003259 vp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003260 break;
3261 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00003262 vp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00003263 break;
3264 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00003265 vp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003266 break;
3267 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00003268 vp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003269 break;
3270 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00003271 vp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003272 break;
3273 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00003274 vp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003275 break;
3276 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00003277 vp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003278 break;
3279 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003280 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003281 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003282
Jouk Jansen40322e12004-04-05 08:50:36 +00003283 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003284 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003285 return 1;
3286 }
3287 break;
3288
3289 case OP_ALU_TRI:
3290 switch (code) {
3291 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00003292 vp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003293 break;
3294 }
3295
Keith Whitwell7c26b612005-04-21 14:46:57 +00003296 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003297 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003298
Jouk Jansen40322e12004-04-05 08:50:36 +00003299 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003300 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003301 return 1;
3302 }
3303 break;
3304
3305 case OP_ALU_SWZ:
3306 switch (code) {
3307 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00003308 vp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003309 break;
3310 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003311 {
Brian Paul32df89e2005-10-29 18:26:43 +00003312 GLubyte swizzle[4];
3313 GLubyte negateMask;
3314 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003315 enum register_file file;
3316 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003317
Keith Whitwell7c26b612005-04-21 14:46:57 +00003318 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3319 return 1;
3320
Brian Paul32df89e2005-10-29 18:26:43 +00003321 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003322 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003323 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3324 vp->SrcReg[0].File = file;
3325 vp->SrcReg[0].Index = index;
Brian Paul7e807512005-11-05 17:10:45 +00003326 vp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003327 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3328 swizzle[1],
3329 swizzle[2],
3330 swizzle[3]);
3331 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003332 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003333 break;
3334 }
3335 return 0;
3336}
3337
3338#if DEBUG_PARSING
3339
3340static GLvoid
3341print_state_token (GLint token)
3342{
3343 switch (token) {
3344 case STATE_MATERIAL:
3345 fprintf (stderr, "STATE_MATERIAL ");
3346 break;
3347 case STATE_LIGHT:
3348 fprintf (stderr, "STATE_LIGHT ");
3349 break;
3350
3351 case STATE_LIGHTMODEL_AMBIENT:
3352 fprintf (stderr, "STATE_AMBIENT ");
3353 break;
3354
3355 case STATE_LIGHTMODEL_SCENECOLOR:
3356 fprintf (stderr, "STATE_SCENECOLOR ");
3357 break;
3358
3359 case STATE_LIGHTPROD:
3360 fprintf (stderr, "STATE_LIGHTPROD ");
3361 break;
3362
3363 case STATE_TEXGEN:
3364 fprintf (stderr, "STATE_TEXGEN ");
3365 break;
3366
3367 case STATE_FOG_COLOR:
3368 fprintf (stderr, "STATE_FOG_COLOR ");
3369 break;
3370
3371 case STATE_FOG_PARAMS:
3372 fprintf (stderr, "STATE_FOG_PARAMS ");
3373 break;
3374
3375 case STATE_CLIPPLANE:
3376 fprintf (stderr, "STATE_CLIPPLANE ");
3377 break;
3378
3379 case STATE_POINT_SIZE:
3380 fprintf (stderr, "STATE_POINT_SIZE ");
3381 break;
3382
3383 case STATE_POINT_ATTENUATION:
3384 fprintf (stderr, "STATE_ATTENUATION ");
3385 break;
3386
3387 case STATE_MATRIX:
3388 fprintf (stderr, "STATE_MATRIX ");
3389 break;
3390
3391 case STATE_MODELVIEW:
3392 fprintf (stderr, "STATE_MODELVIEW ");
3393 break;
3394
3395 case STATE_PROJECTION:
3396 fprintf (stderr, "STATE_PROJECTION ");
3397 break;
3398
3399 case STATE_MVP:
3400 fprintf (stderr, "STATE_MVP ");
3401 break;
3402
3403 case STATE_TEXTURE:
3404 fprintf (stderr, "STATE_TEXTURE ");
3405 break;
3406
3407 case STATE_PROGRAM:
3408 fprintf (stderr, "STATE_PROGRAM ");
3409 break;
3410
3411 case STATE_MATRIX_INVERSE:
3412 fprintf (stderr, "STATE_INVERSE ");
3413 break;
3414
3415 case STATE_MATRIX_TRANSPOSE:
3416 fprintf (stderr, "STATE_TRANSPOSE ");
3417 break;
3418
3419 case STATE_MATRIX_INVTRANS:
3420 fprintf (stderr, "STATE_INVTRANS ");
3421 break;
3422
3423 case STATE_AMBIENT:
3424 fprintf (stderr, "STATE_AMBIENT ");
3425 break;
3426
3427 case STATE_DIFFUSE:
3428 fprintf (stderr, "STATE_DIFFUSE ");
3429 break;
3430
3431 case STATE_SPECULAR:
3432 fprintf (stderr, "STATE_SPECULAR ");
3433 break;
3434
3435 case STATE_EMISSION:
3436 fprintf (stderr, "STATE_EMISSION ");
3437 break;
3438
3439 case STATE_SHININESS:
3440 fprintf (stderr, "STATE_SHININESS ");
3441 break;
3442
3443 case STATE_HALF:
3444 fprintf (stderr, "STATE_HALF ");
3445 break;
3446
3447 case STATE_POSITION:
3448 fprintf (stderr, "STATE_POSITION ");
3449 break;
3450
3451 case STATE_ATTENUATION:
3452 fprintf (stderr, "STATE_ATTENUATION ");
3453 break;
3454
3455 case STATE_SPOT_DIRECTION:
3456 fprintf (stderr, "STATE_DIRECTION ");
3457 break;
3458
3459 case STATE_TEXGEN_EYE_S:
3460 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3461 break;
3462
3463 case STATE_TEXGEN_EYE_T:
3464 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3465 break;
3466
3467 case STATE_TEXGEN_EYE_R:
3468 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3469 break;
3470
3471 case STATE_TEXGEN_EYE_Q:
3472 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3473 break;
3474
3475 case STATE_TEXGEN_OBJECT_S:
3476 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3477 break;
3478
3479 case STATE_TEXGEN_OBJECT_T:
3480 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3481 break;
3482
3483 case STATE_TEXGEN_OBJECT_R:
3484 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3485 break;
3486
3487 case STATE_TEXGEN_OBJECT_Q:
3488 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3489 break;
3490
3491 case STATE_TEXENV_COLOR:
3492 fprintf (stderr, "STATE_TEXENV_COLOR ");
3493 break;
3494
3495 case STATE_DEPTH_RANGE:
3496 fprintf (stderr, "STATE_DEPTH_RANGE ");
3497 break;
3498
3499 case STATE_VERTEX_PROGRAM:
3500 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3501 break;
3502
3503 case STATE_FRAGMENT_PROGRAM:
3504 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3505 break;
3506
3507 case STATE_ENV:
3508 fprintf (stderr, "STATE_ENV ");
3509 break;
3510
3511 case STATE_LOCAL:
3512 fprintf (stderr, "STATE_LOCAL ");
3513 break;
3514
3515 }
3516 fprintf (stderr, "[%d] ", token);
3517}
3518
3519
3520static GLvoid
3521debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3522 struct arb_program *Program)
3523{
3524 struct var_cache *vc;
3525 GLint a, b;
3526
3527 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3528
3529 /* First of all, print out the contents of the var_cache */
3530 vc = vc_head;
3531 while (vc) {
3532 fprintf (stderr, "[%x]\n", vc);
3533 switch (vc->type) {
3534 case vt_none:
3535 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3536 break;
3537 case vt_attrib:
3538 fprintf (stderr, "ATTRIB %s\n", vc->name);
3539 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3540 break;
3541 case vt_param:
3542 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3543 vc->param_binding_begin, vc->param_binding_length);
3544 b = vc->param_binding_begin;
3545 for (a = 0; a < vc->param_binding_length; a++) {
3546 fprintf (stderr, "%s\n",
3547 Program->Parameters->Parameters[a + b].Name);
3548 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3549 print_state_token (Program->Parameters->Parameters[a + b].
3550 StateIndexes[0]);
3551 print_state_token (Program->Parameters->Parameters[a + b].
3552 StateIndexes[1]);
3553 print_state_token (Program->Parameters->Parameters[a + b].
3554 StateIndexes[2]);
3555 print_state_token (Program->Parameters->Parameters[a + b].
3556 StateIndexes[3]);
3557 print_state_token (Program->Parameters->Parameters[a + b].
3558 StateIndexes[4]);
3559 print_state_token (Program->Parameters->Parameters[a + b].
3560 StateIndexes[5]);
3561 }
3562 else
3563 fprintf (stderr, "%f %f %f %f\n",
3564 Program->Parameters->Parameters[a + b].Values[0],
3565 Program->Parameters->Parameters[a + b].Values[1],
3566 Program->Parameters->Parameters[a + b].Values[2],
3567 Program->Parameters->Parameters[a + b].Values[3]);
3568 }
3569 break;
3570 case vt_temp:
3571 fprintf (stderr, "TEMP %s\n", vc->name);
3572 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3573 break;
3574 case vt_output:
3575 fprintf (stderr, "OUTPUT %s\n", vc->name);
3576 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3577 break;
3578 case vt_alias:
3579 fprintf (stderr, "ALIAS %s\n", vc->name);
3580 fprintf (stderr, " binding: 0x%x (%s)\n",
3581 vc->alias_binding, vc->alias_binding->name);
3582 break;
3583 }
3584 vc = vc->next;
3585 }
3586}
3587
Brian Paul72030e02005-11-03 03:30:34 +00003588#endif /* DEBUG_PARSING */
Brian Paul7aebaf32005-10-30 21:23:23 +00003589
3590
3591/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003592 * The main loop for parsing a fragment or vertex program
3593 *
Brian Paul72030e02005-11-03 03:30:34 +00003594 * \return 1 on error, 0 on success
Jouk Jansen40322e12004-04-05 08:50:36 +00003595 */
Brian Paul72030e02005-11-03 03:30:34 +00003596static GLint
Brian Paul45703642005-10-29 15:52:31 +00003597parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3598 struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003599{
Brian Paul72030e02005-11-03 03:30:34 +00003600 const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
3601 ? ctx->Const.FragmentProgram.MaxInstructions
3602 : ctx->Const.VertexProgram.MaxInstructions;
Jouk Jansen40322e12004-04-05 08:50:36 +00003603 GLint err = 0;
3604
Brian Paul72030e02005-11-03 03:30:34 +00003605 ASSERT(MAX_INSTRUCTIONS >= maxInst);
3606
Jouk Jansen40322e12004-04-05 08:50:36 +00003607 Program->MajorVersion = (GLuint) * inst++;
3608 Program->MinorVersion = (GLuint) * inst++;
3609
3610 while (*inst != END) {
3611 switch (*inst++) {
3612
3613 case OPTION:
3614 switch (*inst++) {
3615 case ARB_PRECISION_HINT_FASTEST:
3616 Program->PrecisionOption = GL_FASTEST;
3617 break;
3618
3619 case ARB_PRECISION_HINT_NICEST:
3620 Program->PrecisionOption = GL_NICEST;
3621 break;
3622
3623 case ARB_FOG_EXP:
3624 Program->FogOption = GL_EXP;
3625 break;
3626
3627 case ARB_FOG_EXP2:
3628 Program->FogOption = GL_EXP2;
3629 break;
3630
3631 case ARB_FOG_LINEAR:
3632 Program->FogOption = GL_LINEAR;
3633 break;
3634
3635 case ARB_POSITION_INVARIANT:
3636 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
Brian Paul45cd2f92005-11-03 02:25:10 +00003637 Program->HintPositionInvariant = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003638 break;
3639
3640 case ARB_FRAGMENT_PROGRAM_SHADOW:
3641 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3642 /* TODO ARB_fragment_program_shadow code */
3643 }
3644 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003645
3646 case ARB_DRAW_BUFFERS:
3647 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3648 /* do nothing for now */
3649 }
3650 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003651 }
3652 break;
3653
3654 case INSTRUCTION:
Brian Paul72030e02005-11-03 03:30:34 +00003655 /* check length */
3656 if (Program->Base.NumInstructions + 1 >= maxInst) {
3657 const char *msg = "Max instruction count exceeded";
3658 _mesa_set_program_error(ctx, Program->Position, msg);
3659 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
3660 return 1;
3661 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003662 Program->Position = parse_position (&inst);
Brian Paul72030e02005-11-03 03:30:34 +00003663 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003664 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003665 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003666 &Program->FPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003667 }
3668 else {
Jouk Jansen40322e12004-04-05 08:50:36 +00003669 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003670 &Program->VPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003671 }
3672
Brian Paul72030e02005-11-03 03:30:34 +00003673 /* increment instuction count */
Jouk Jansen40322e12004-04-05 08:50:36 +00003674 Program->Base.NumInstructions++;
3675 break;
3676
3677 case DECLARATION:
3678 err = parse_declaration (ctx, &inst, vc_head, Program);
3679 break;
3680
3681 default:
3682 break;
3683 }
3684
3685 if (err)
3686 break;
3687 }
3688
3689 /* Finally, tag on an OPCODE_END instruction */
3690 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00003691 const GLuint numInst = Program->Base.NumInstructions;
Brian Paul7e807512005-11-05 17:10:45 +00003692 _mesa_init_instruction(Program->FPInstructions + numInst);
3693 Program->FPInstructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003694 /* YYY Wrong Position in program, whatever, at least not random -> crash
3695 Program->Position = parse_position (&inst);
3696 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003697 Program->FPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003698 }
3699 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00003700 const GLuint numInst = Program->Base.NumInstructions;
Brian Paul7e807512005-11-05 17:10:45 +00003701 _mesa_init_instruction(Program->VPInstructions + numInst);
3702 Program->VPInstructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003703 /* YYY Wrong Position in program, whatever, at least not random -> crash
3704 Program->Position = parse_position (&inst);
3705 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003706 Program->VPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003707 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003708 Program->Base.NumInstructions++;
3709
Brian Paul05051032005-11-01 04:36:33 +00003710 /*
3711 * Initialize native counts to logical counts. The device driver may
3712 * change them if program is translated into a hardware program.
3713 */
3714 Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
3715 Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
3716 Program->Base.NumNativeParameters = Program->Base.NumParameters;
3717 Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
3718 Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
3719 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3720 struct fragment_program *fp = (struct fragment_program *) Program;
3721 fp->NumNativeAluInstructions = fp->NumAluInstructions;
3722 fp->NumNativeTexInstructions = fp->NumTexInstructions;
3723 fp->NumNativeTexIndirections = fp->NumTexIndirections;
3724 }
3725
Jouk Jansen40322e12004-04-05 08:50:36 +00003726 return err;
3727}
3728
Brian Paul7aebaf32005-10-30 21:23:23 +00003729
Jouk Jansen40322e12004-04-05 08:50:36 +00003730/* XXX temporary */
Brian Paula6c423d2004-08-25 15:59:48 +00003731__extension__ static char core_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +00003732#include "grammar_syn.h"
3733;
3734
Brian Paul7aebaf32005-10-30 21:23:23 +00003735
Jouk Jansen40322e12004-04-05 08:50:36 +00003736static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3737{
3738 char error_msg[300];
3739 GLint error_pos;
3740
3741 if (grammar_set_reg8 (id, name, value))
3742 return 0;
3743
3744 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3745 _mesa_set_program_error (ctx, error_pos, error_msg);
3746 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3747 return 1;
3748}
3749
3750static int extension_is_supported (const GLubyte *ext)
3751{
Brian Paul832026f2005-11-08 14:41:41 +00003752 const GLubyte *extensions = _mesa_GetString(GL_EXTENSIONS);
Jouk Jansen40322e12004-04-05 08:50:36 +00003753 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
Karl Schultz6258b762005-05-05 21:08:07 +00003754 const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
Jouk Jansen40322e12004-04-05 08:50:36 +00003755
3756 while (extensions < end)
3757 {
Brian Paulb3aefd12005-09-19 20:12:32 +00003758 const GLubyte *name_end = (const GLubyte *) _mesa_strstr ((const char *) extensions, " ");
Jouk Jansen40322e12004-04-05 08:50:36 +00003759 if (name_end == NULL)
3760 name_end = end;
3761 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3762 (const char *) extensions, ext_len) == 0)
3763 return 1;
3764 extensions = name_end + 1;
3765 }
3766
3767 return 0;
3768}
3769
3770static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3771{
3772 if (extension_is_supported (extname))
3773 if (set_reg8 (ctx, id, name, 0x01))
3774 return 1;
3775 return 0;
3776}
3777
3778/**
3779 * This kicks everything off.
3780 *
3781 * \param ctx - The GL Context
3782 * \param str - The program string
3783 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003784 * \param program - The arb_program struct to return all the parsed info in
3785 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003786 */
Brian Paul45703642005-10-29 15:52:31 +00003787GLboolean
Jouk Jansen40322e12004-04-05 08:50:36 +00003788_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3789 struct arb_program * program)
3790{
3791 GLint a, err, error_pos;
3792 char error_msg[300];
3793 GLuint parsed_len;
3794 struct var_cache *vc_head;
3795 grammar arbprogram_syn_id;
3796 GLubyte *parsed, *inst;
3797 GLubyte *strz = NULL;
3798 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3799
Brian Paul7f76b8f2004-09-10 01:05:39 +00003800 /* Reset error state */
3801 _mesa_set_program_error(ctx, -1, NULL);
3802
Jouk Jansen40322e12004-04-05 08:50:36 +00003803#if DEBUG_PARSING
3804 fprintf (stderr, "Loading grammar text!\n");
3805#endif
3806
3807 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3808 if (!arbprogram_syn_is_ok) {
3809 grammar grammar_syn_id;
3810 GLint err;
3811 GLuint parsed_len;
3812 byte *parsed;
3813
3814 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3815 if (grammar_syn_id == 0) {
3816 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3817 _mesa_set_program_error (ctx, error_pos, error_msg);
3818 _mesa_error (ctx, GL_INVALID_OPERATION,
3819 "Error loading grammar rule set");
Brian Paul45703642005-10-29 15:52:31 +00003820 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003821 }
3822
3823 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3824
Brian Paul45703642005-10-29 15:52:31 +00003825 /* NOTE: we can't destroy grammar_syn_id right here because
3826 * grammar_destroy() can reset the last error
3827 */
Jouk Jansen40322e12004-04-05 08:50:36 +00003828 if (err == 0) {
3829 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3830 _mesa_set_program_error (ctx, error_pos, error_msg);
3831 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3832
3833 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003834 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003835 }
3836
3837 grammar_destroy (grammar_syn_id);
3838
3839 arbprogram_syn_is_ok = 1;
3840 }
3841
3842 /* create the grammar object */
3843 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3844 if (arbprogram_syn_id == 0) {
3845 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3846 _mesa_set_program_error (ctx, error_pos, error_msg);
3847 _mesa_error (ctx, GL_INVALID_OPERATION,
3848 "Error loading grammer rule set");
Brian Paul45703642005-10-29 15:52:31 +00003849 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003850 }
3851
3852 /* Set program_target register value */
3853 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3854 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3855 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003856 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003857 }
3858
3859 /* Enable all active extensions */
3860 if (enable_ext (ctx, arbprogram_syn_id,
3861 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3862 enable_ext (ctx, arbprogram_syn_id,
3863 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
3864 enable_ext (ctx, arbprogram_syn_id,
3865 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
3866 enable_ext (ctx, arbprogram_syn_id,
3867 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
3868 enable_ext (ctx, arbprogram_syn_id,
3869 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
3870 enable_ext (ctx, arbprogram_syn_id,
3871 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
3872 enable_ext (ctx, arbprogram_syn_id,
3873 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
3874 enable_ext (ctx, arbprogram_syn_id,
Brian Pauledfe0fe2004-08-20 14:21:20 +00003875 (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
3876 enable_ext (ctx, arbprogram_syn_id,
Jouk Jansen40322e12004-04-05 08:50:36 +00003877 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
3878 enable_ext (ctx, arbprogram_syn_id,
3879 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
3880 enable_ext (ctx, arbprogram_syn_id,
Michal Krolad22ce82004-10-11 08:13:25 +00003881 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
3882 enable_ext (ctx, arbprogram_syn_id,
3883 (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003884 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003885 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003886 }
3887
3888 /* check for NULL character occurences */
3889 {
3890 int i;
3891 for (i = 0; i < len; i++)
3892 if (str[i] == '\0') {
3893 _mesa_set_program_error (ctx, i, "invalid character");
3894 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
3895
3896 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003897 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003898 }
3899 }
3900
3901 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003902 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003903 if (!strz) {
3904 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glprogramStringARB");
3905 return GL_FALSE;
3906 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003907 _mesa_memcpy (strz, str, len);
3908 strz[len] = '\0';
3909
3910#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003911 fprintf (stderr, "Checking Grammar!\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00003912#endif
Michal Krolb80bc052004-10-21 14:09:54 +00003913 /* do a fast check on program string - initial production buffer is 4K */
3914 err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00003915
3916 /* Syntax parse error */
3917 if (err == 0) {
3918 _mesa_free (strz);
3919 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3920 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul45703642005-10-29 15:52:31 +00003921 _mesa_error (ctx, GL_INVALID_OPERATION, "glprogramStringARB(syntax error)");
Brian Paul5fe90292004-07-20 21:15:13 +00003922
3923 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00003924#if DEBUG_PARSING
3925 do {
Brian Paul5fe90292004-07-20 21:15:13 +00003926 int line, col;
3927 char *s;
Brian Paul45703642005-10-29 15:52:31 +00003928 fprintf(stderr, "program: %s\n", (char *) strz);
3929 fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
3930 s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos, &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00003931 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
3932 } while (0)
3933#endif
Brian Paul5fe90292004-07-20 21:15:13 +00003934
Jouk Jansen40322e12004-04-05 08:50:36 +00003935 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003936 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003937 }
3938
3939#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003940 fprintf (stderr, "Destroying grammer dict [parse retval: %d]\n", err);
Jouk Jansen40322e12004-04-05 08:50:36 +00003941#endif
3942 grammar_destroy (arbprogram_syn_id);
3943
3944 /* Initialize the arb_program struct */
3945 program->Base.String = strz;
3946 program->Base.NumInstructions =
3947 program->Base.NumTemporaries =
3948 program->Base.NumParameters =
3949 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
Brian Paulde997602005-11-12 17:53:14 +00003950 program->Base.Parameters = _mesa_new_parameter_list ();
3951 program->Base.InputsRead = 0x0;
3952 program->Base.OutputsWritten = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003953 program->Position = 0;
3954 program->MajorVersion = program->MinorVersion = 0;
3955 program->PrecisionOption = GL_DONT_CARE;
3956 program->FogOption = GL_NONE;
3957 program->HintPositionInvariant = GL_FALSE;
3958 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
Brian Paul45cd2f92005-11-03 02:25:10 +00003959 program->TexturesUsed[a] = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003960 program->NumAluInstructions =
3961 program->NumTexInstructions =
3962 program->NumTexIndirections = 0;
3963
Keith Whitwellc3626a92005-11-01 17:25:49 +00003964 program->UsesKill = 0;
3965
Jouk Jansen40322e12004-04-05 08:50:36 +00003966 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00003967 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003968
3969 /* Start examining the tokens in the array */
3970 inst = parsed;
3971
3972 /* Check the grammer rev */
3973 if (*inst++ != REVISION) {
3974 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00003975 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul45cd2f92005-11-03 02:25:10 +00003976 "glProgramStringARB(Grammar version mismatch)");
Brian Paul45703642005-10-29 15:52:31 +00003977 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003978 }
3979 else {
Michal Krolb80bc052004-10-21 14:09:54 +00003980 /* ignore program target */
3981 inst++;
Jouk Jansen40322e12004-04-05 08:50:36 +00003982
3983 err = parse_arb_program (ctx, inst, &vc_head, program);
3984#if DEBUG_PARSING
3985 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
3986#endif
3987 }
3988
3989 /*debug_variables(ctx, vc_head, program); */
3990
3991 /* We're done with the parsed binary array */
3992 var_cache_destroy (&vc_head);
3993
3994 _mesa_free (parsed);
3995#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003996 fprintf (stderr, "_mesa_parse_arb_program() done\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00003997#endif
Brian Paul45703642005-10-29 15:52:31 +00003998
3999 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00004000}