blob: 377b9bb8623a1b27a47245c89e2fb99b8104bf6f [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
33#include "mtypes.h"
34#include "glheader.h"
35#include "context.h"
36#include "hash.h"
37#include "imports.h"
38#include "macros.h"
39#include "program.h"
Brian Paul7e807512005-11-05 17:10:45 +000040#include "program_instruction.h"
Jouk Jansen40322e12004-04-05 08:50:36 +000041#include "arbprogparse.h"
42#include "grammar_mesa.h"
Brian Paul32df89e2005-10-29 18:26:43 +000043#include "program.h"
Ian Romanick9bdfee32005-07-18 12:31:24 +000044#include "dispatch.h"
45
Alan Hourihane38b317d2004-12-14 09:11:52 +000046#ifndef __extension__
47#if !defined(__GNUC__) || (__GNUC__ < 2) || \
48 ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
Brian Paula6c423d2004-08-25 15:59:48 +000049# define __extension__
50#endif
Alan Hourihane38b317d2004-12-14 09:11:52 +000051#endif
Brian Paula6c423d2004-08-25 15:59:48 +000052
Jouk Jansen40322e12004-04-05 08:50:36 +000053/* TODO:
54 * Fragment Program Stuff:
55 * -----------------------------------------------------
56 *
57 * - things from Michal's email
58 * + overflow on atoi
59 * + not-overflowing floats (don't use parse_integer..)
60 * + can remove range checking in arbparse.c
61 *
62 * - check all limits of number of various variables
63 * + parameters
64 *
65 * - test! test! test!
66 *
67 * Vertex Program Stuff:
68 * -----------------------------------------------------
69 * - Optimize param array usage and count limits correctly, see spec,
70 * section 2.14.3.7
71 * + Record if an array is reference absolutly or relatively (or both)
72 * + For absolute arrays, store a bitmap of accesses
73 * + For single parameters, store an access flag
74 * + After parsing, make a parameter cleanup and merging pass, where
75 * relative arrays are layed out first, followed by abs arrays, and
76 * finally single state.
77 * + Remap offsets for param src and dst registers
78 * + Now we can properly count parameter usage
79 *
80 * - Multiple state binding errors in param arrays (see spec, just before
81 * section 2.14.3.3)
82 * - grep for XXX
83 *
84 * Mesa Stuff
85 * -----------------------------------------------------
86 * - User clipping planes vs. PositionInvariant
87 * - Is it sufficient to just multiply by the mvp to transform in the
88 * PositionInvariant case? Or do we need something more involved?
89 *
90 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
91 * - fetch state listed in program_parameters list
92 * + WTF should this go???
93 * + currently in nvvertexec.c and s_nvfragprog.c
94 *
95 * - allow for multiple address registers (and fetch address regs properly)
96 *
97 * Cosmetic Stuff
98 * -----------------------------------------------------
99 * - remove any leftover unused grammer.c stuff (dict_ ?)
100 * - fix grammer.c error handling so its not static
101 * - #ifdef around stuff pertaining to extentions
102 *
103 * Outstanding Questions:
104 * -----------------------------------------------------
105 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
106 * what gets hacked off because of this:
107 * + VERTEX_ATTRIB_MATRIXINDEX
108 * + VERTEX_ATTRIB_WEIGHT
109 * + MATRIX_MODELVIEW
110 * + MATRIX_PALETTE
111 *
112 * - When can we fetch env/local params from their own register files, and
113 * when to we have to fetch them into the main state register file?
114 * (think arrays)
115 *
116 * Grammar Changes:
117 * -----------------------------------------------------
118 */
119
120/* Changes since moving the file to shader directory
121
1222004-III-4 ------------------------------------------------------------
123- added #include "grammar_mesa.h"
124- removed grammar specific code part (it resides now in grammar.c)
125- added GL_ARB_fragment_program_shadow tokens
126- modified #include "arbparse_syn.h"
127- major changes inside _mesa_parse_arb_program()
128- check the program string for '\0' characters
129- copy the program string to a one-byte-longer location to have
130 it null-terminated
131- position invariance test (not writing to result.position) moved
132 to syntax part
133*/
134
135typedef GLubyte *production;
136
137/**
138 * This is the text describing the rules to parse the grammar
139 */
Brian Paula6c423d2004-08-25 15:59:48 +0000140__extension__ static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000141#include "arbprogram_syn.h"
142;
143
144/**
145 * These should match up with the values defined in arbprogram.syn
146 */
147
148/*
149 Changes:
150 - changed and merged V_* and F_* opcode values to OP_*.
151 - added GL_ARB_fragment_program_shadow specific tokens (michal)
152*/
Michal Krolb80bc052004-10-21 14:09:54 +0000153#define REVISION 0x09
Jouk Jansen40322e12004-04-05 08:50:36 +0000154
155/* program type */
156#define FRAGMENT_PROGRAM 0x01
157#define VERTEX_PROGRAM 0x02
158
159/* program section */
160#define OPTION 0x01
161#define INSTRUCTION 0x02
162#define DECLARATION 0x03
163#define END 0x04
164
Michal Krolb80bc052004-10-21 14:09:54 +0000165/* GL_ARB_fragment_program option */
166#define ARB_PRECISION_HINT_FASTEST 0x00
167#define ARB_PRECISION_HINT_NICEST 0x01
168#define ARB_FOG_EXP 0x02
169#define ARB_FOG_EXP2 0x03
170#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000171
Michal Krolb80bc052004-10-21 14:09:54 +0000172/* GL_ARB_vertex_program option */
173#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000174
Michal Krolb80bc052004-10-21 14:09:54 +0000175/* GL_ARB_fragment_program_shadow option */
176#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000177
Michal Krolb80bc052004-10-21 14:09:54 +0000178/* GL_ARB_draw_buffers option */
179#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000180
Jouk Jansen40322e12004-04-05 08:50:36 +0000181/* GL_ARB_fragment_program instruction class */
182#define OP_ALU_INST 0x00
183#define OP_TEX_INST 0x01
184
185/* GL_ARB_vertex_program instruction class */
186/* OP_ALU_INST */
187
188/* GL_ARB_fragment_program instruction type */
189#define OP_ALU_VECTOR 0x00
190#define OP_ALU_SCALAR 0x01
191#define OP_ALU_BINSC 0x02
192#define OP_ALU_BIN 0x03
193#define OP_ALU_TRI 0x04
194#define OP_ALU_SWZ 0x05
195#define OP_TEX_SAMPLE 0x06
196#define OP_TEX_KIL 0x07
197
198/* GL_ARB_vertex_program instruction type */
199#define OP_ALU_ARL 0x08
200/* OP_ALU_VECTOR */
201/* OP_ALU_SCALAR */
202/* OP_ALU_BINSC */
203/* OP_ALU_BIN */
204/* OP_ALU_TRI */
205/* OP_ALU_SWZ */
206
207/* GL_ARB_fragment_program instruction code */
208#define OP_ABS 0x00
209#define OP_ABS_SAT 0x1B
210#define OP_FLR 0x09
211#define OP_FLR_SAT 0x26
212#define OP_FRC 0x0A
213#define OP_FRC_SAT 0x27
214#define OP_LIT 0x0C
215#define OP_LIT_SAT 0x2A
216#define OP_MOV 0x11
217#define OP_MOV_SAT 0x30
218#define OP_COS 0x1F
219#define OP_COS_SAT 0x20
220#define OP_EX2 0x07
221#define OP_EX2_SAT 0x25
222#define OP_LG2 0x0B
223#define OP_LG2_SAT 0x29
224#define OP_RCP 0x14
225#define OP_RCP_SAT 0x33
226#define OP_RSQ 0x15
227#define OP_RSQ_SAT 0x34
228#define OP_SIN 0x38
229#define OP_SIN_SAT 0x39
230#define OP_SCS 0x35
231#define OP_SCS_SAT 0x36
232#define OP_POW 0x13
233#define OP_POW_SAT 0x32
234#define OP_ADD 0x01
235#define OP_ADD_SAT 0x1C
236#define OP_DP3 0x03
237#define OP_DP3_SAT 0x21
238#define OP_DP4 0x04
239#define OP_DP4_SAT 0x22
240#define OP_DPH 0x05
241#define OP_DPH_SAT 0x23
242#define OP_DST 0x06
243#define OP_DST_SAT 0x24
244#define OP_MAX 0x0F
245#define OP_MAX_SAT 0x2E
246#define OP_MIN 0x10
247#define OP_MIN_SAT 0x2F
248#define OP_MUL 0x12
249#define OP_MUL_SAT 0x31
250#define OP_SGE 0x16
251#define OP_SGE_SAT 0x37
252#define OP_SLT 0x17
253#define OP_SLT_SAT 0x3A
254#define OP_SUB 0x18
255#define OP_SUB_SAT 0x3B
256#define OP_XPD 0x1A
257#define OP_XPD_SAT 0x43
258#define OP_CMP 0x1D
259#define OP_CMP_SAT 0x1E
260#define OP_LRP 0x2B
261#define OP_LRP_SAT 0x2C
262#define OP_MAD 0x0E
263#define OP_MAD_SAT 0x2D
264#define OP_SWZ 0x19
265#define OP_SWZ_SAT 0x3C
266#define OP_TEX 0x3D
267#define OP_TEX_SAT 0x3E
268#define OP_TXB 0x3F
269#define OP_TXB_SAT 0x40
270#define OP_TXP 0x41
271#define OP_TXP_SAT 0x42
272#define OP_KIL 0x28
273
274/* GL_ARB_vertex_program instruction code */
275#define OP_ARL 0x02
276/* OP_ABS */
277/* OP_FLR */
278/* OP_FRC */
279/* OP_LIT */
280/* OP_MOV */
281/* OP_EX2 */
282#define OP_EXP 0x08
283/* OP_LG2 */
284#define OP_LOG 0x0D
285/* OP_RCP */
286/* OP_RSQ */
287/* OP_POW */
288/* OP_ADD */
289/* OP_DP3 */
290/* OP_DP4 */
291/* OP_DPH */
292/* OP_DST */
293/* OP_MAX */
294/* OP_MIN */
295/* OP_MUL */
296/* OP_SGE */
297/* OP_SLT */
298/* OP_SUB */
299/* OP_XPD */
300/* OP_MAD */
301/* OP_SWZ */
302
303/* fragment attribute binding */
304#define FRAGMENT_ATTRIB_COLOR 0x01
305#define FRAGMENT_ATTRIB_TEXCOORD 0x02
306#define FRAGMENT_ATTRIB_FOGCOORD 0x03
307#define FRAGMENT_ATTRIB_POSITION 0x04
308
309/* vertex attribute binding */
310#define VERTEX_ATTRIB_POSITION 0x01
311#define VERTEX_ATTRIB_WEIGHT 0x02
312#define VERTEX_ATTRIB_NORMAL 0x03
313#define VERTEX_ATTRIB_COLOR 0x04
314#define VERTEX_ATTRIB_FOGCOORD 0x05
315#define VERTEX_ATTRIB_TEXCOORD 0x06
316#define VERTEX_ATTRIB_MATRIXINDEX 0x07
317#define VERTEX_ATTRIB_GENERIC 0x08
318
319/* fragment result binding */
320#define FRAGMENT_RESULT_COLOR 0x01
321#define FRAGMENT_RESULT_DEPTH 0x02
322
323/* vertex result binding */
324#define VERTEX_RESULT_POSITION 0x01
325#define VERTEX_RESULT_COLOR 0x02
326#define VERTEX_RESULT_FOGCOORD 0x03
327#define VERTEX_RESULT_POINTSIZE 0x04
328#define VERTEX_RESULT_TEXCOORD 0x05
329
330/* texture target */
331#define TEXTARGET_1D 0x01
332#define TEXTARGET_2D 0x02
333#define TEXTARGET_3D 0x03
334#define TEXTARGET_RECT 0x04
335#define TEXTARGET_CUBE 0x05
336/* GL_ARB_fragment_program_shadow */
337#define TEXTARGET_SHADOW1D 0x06
338#define TEXTARGET_SHADOW2D 0x07
339#define TEXTARGET_SHADOWRECT 0x08
340
341/* face type */
342#define FACE_FRONT 0x00
343#define FACE_BACK 0x01
344
345/* color type */
346#define COLOR_PRIMARY 0x00
347#define COLOR_SECONDARY 0x01
348
349/* component */
350#define COMPONENT_X 0x00
351#define COMPONENT_Y 0x01
352#define COMPONENT_Z 0x02
353#define COMPONENT_W 0x03
354#define COMPONENT_0 0x04
355#define COMPONENT_1 0x05
356
357/* array index type */
358#define ARRAY_INDEX_ABSOLUTE 0x00
359#define ARRAY_INDEX_RELATIVE 0x01
360
361/* matrix name */
362#define MATRIX_MODELVIEW 0x01
363#define MATRIX_PROJECTION 0x02
364#define MATRIX_MVP 0x03
365#define MATRIX_TEXTURE 0x04
366#define MATRIX_PALETTE 0x05
367#define MATRIX_PROGRAM 0x06
368
369/* matrix modifier */
370#define MATRIX_MODIFIER_IDENTITY 0x00
371#define MATRIX_MODIFIER_INVERSE 0x01
372#define MATRIX_MODIFIER_TRANSPOSE 0x02
373#define MATRIX_MODIFIER_INVTRANS 0x03
374
375/* constant type */
376#define CONSTANT_SCALAR 0x01
377#define CONSTANT_VECTOR 0x02
378
379/* program param type */
380#define PROGRAM_PARAM_ENV 0x01
381#define PROGRAM_PARAM_LOCAL 0x02
382
383/* register type */
384#define REGISTER_ATTRIB 0x01
385#define REGISTER_PARAM 0x02
386#define REGISTER_RESULT 0x03
387#define REGISTER_ESTABLISHED_NAME 0x04
388
389/* param binding */
390#define PARAM_NULL 0x00
391#define PARAM_ARRAY_ELEMENT 0x01
392#define PARAM_STATE_ELEMENT 0x02
393#define PARAM_PROGRAM_ELEMENT 0x03
394#define PARAM_PROGRAM_ELEMENTS 0x04
395#define PARAM_CONSTANT 0x05
396
397/* param state property */
398#define STATE_MATERIAL_PARSER 0x01
399#define STATE_LIGHT_PARSER 0x02
400#define STATE_LIGHT_MODEL 0x03
401#define STATE_LIGHT_PROD 0x04
402#define STATE_FOG 0x05
403#define STATE_MATRIX_ROWS 0x06
404/* GL_ARB_fragment_program */
405#define STATE_TEX_ENV 0x07
406#define STATE_DEPTH 0x08
407/* GL_ARB_vertex_program */
408#define STATE_TEX_GEN 0x09
409#define STATE_CLIP_PLANE 0x0A
410#define STATE_POINT 0x0B
411
412/* state material property */
413#define MATERIAL_AMBIENT 0x01
414#define MATERIAL_DIFFUSE 0x02
415#define MATERIAL_SPECULAR 0x03
416#define MATERIAL_EMISSION 0x04
417#define MATERIAL_SHININESS 0x05
418
419/* state light property */
420#define LIGHT_AMBIENT 0x01
421#define LIGHT_DIFFUSE 0x02
422#define LIGHT_SPECULAR 0x03
423#define LIGHT_POSITION 0x04
424#define LIGHT_ATTENUATION 0x05
425#define LIGHT_HALF 0x06
426#define LIGHT_SPOT_DIRECTION 0x07
427
428/* state light model property */
429#define LIGHT_MODEL_AMBIENT 0x01
430#define LIGHT_MODEL_SCENECOLOR 0x02
431
432/* state light product property */
433#define LIGHT_PROD_AMBIENT 0x01
434#define LIGHT_PROD_DIFFUSE 0x02
435#define LIGHT_PROD_SPECULAR 0x03
436
437/* state texture environment property */
438#define TEX_ENV_COLOR 0x01
439
440/* state texture generation coord property */
441#define TEX_GEN_EYE 0x01
442#define TEX_GEN_OBJECT 0x02
443
444/* state fog property */
445#define FOG_COLOR 0x01
446#define FOG_PARAMS 0x02
447
448/* state depth property */
449#define DEPTH_RANGE 0x01
450
451/* state point parameters property */
452#define POINT_SIZE 0x01
453#define POINT_ATTENUATION 0x02
454
455/* declaration */
456#define ATTRIB 0x01
457#define PARAM 0x02
458#define TEMP 0x03
459#define OUTPUT 0x04
460#define ALIAS 0x05
461/* GL_ARB_vertex_program */
462#define ADDRESS 0x06
463
464/*-----------------------------------------------------------------------
465 * From here on down is the semantic checking portion
466 *
467 */
468
469/**
470 * Variable Table Handling functions
471 */
472typedef enum
473{
474 vt_none,
475 vt_address,
476 vt_attrib,
477 vt_param,
478 vt_temp,
479 vt_output,
480 vt_alias
481} var_type;
482
483
Brian Paul7aebaf32005-10-30 21:23:23 +0000484/**
485 * Setting an explicit field for each of the binding properties is a bit
486 * wasteful of space, but it should be much more clear when reading later on..
Jouk Jansen40322e12004-04-05 08:50:36 +0000487 */
488struct var_cache
489{
490 GLubyte *name;
491 var_type type;
492 GLuint address_binding; /* The index of the address register we should
493 * be using */
494 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
Jouk Jansen40322e12004-04-05 08:50:36 +0000495 GLuint attrib_is_generic; /* If the attrib was specified through a generic
496 * vertex attrib */
497 GLuint temp_binding; /* The index of the temp register we are to use */
Brian Paul7aebaf32005-10-30 21:23:23 +0000498 GLuint output_binding; /* Output/result register number */
Jouk Jansen40322e12004-04-05 08:50:36 +0000499 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
500 * that this is aliased to */
501 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
502 * PROGRAM_ENV_PARAM} */
503 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
504 * the tokens representing our bound state (or constants)
505 * start */
506 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
507 * we take up with our state tokens or constants. Note that
508 * this is _not_ the same as the number of param registers
509 * we eventually use */
510 struct var_cache *next;
511};
512
513static GLvoid
514var_cache_create (struct var_cache **va)
515{
516 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
517 if (*va) {
518 (**va).name = NULL;
519 (**va).type = vt_none;
520 (**va).attrib_binding = ~0;
521 (**va).attrib_is_generic = 0;
522 (**va).temp_binding = ~0;
523 (**va).output_binding = ~0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000524 (**va).param_binding_type = ~0;
525 (**va).param_binding_begin = ~0;
526 (**va).param_binding_length = ~0;
527 (**va).alias_binding = NULL;
528 (**va).next = NULL;
529 }
530}
531
532static GLvoid
533var_cache_destroy (struct var_cache **va)
534{
535 if (*va) {
536 var_cache_destroy (&(**va).next);
537 _mesa_free (*va);
538 *va = NULL;
539 }
540}
541
542static GLvoid
543var_cache_append (struct var_cache **va, struct var_cache *nv)
544{
545 if (*va)
546 var_cache_append (&(**va).next, nv);
547 else
548 *va = nv;
549}
550
551static struct var_cache *
552var_cache_find (struct var_cache *va, GLubyte * name)
553{
Brian Paul0a360cf2005-01-17 01:21:03 +0000554 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000555
556 while (va) {
Brian Paulaa206952005-09-16 18:14:24 +0000557 if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000558 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000559 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000560 return va;
561 }
562
563 va = va->next;
564 }
565
566 return NULL;
567}
568
569/**
570 * constructs an integer from 4 GLubytes in LE format
571 */
572static GLuint
573parse_position (GLubyte ** inst)
574{
575 GLuint value;
576
577 value = (GLuint) (*(*inst)++);
578 value += (GLuint) (*(*inst)++) * 0x100;
579 value += (GLuint) (*(*inst)++) * 0x10000;
580 value += (GLuint) (*(*inst)++) * 0x1000000;
581
582 return value;
583}
584
585/**
586 * This will, given a string, lookup the string as a variable name in the
587 * var cache. If the name is found, the var cache node corresponding to the
588 * var name is returned. If it is not found, a new entry is allocated
589 *
590 * \param I Points into the binary array where the string identifier begins
591 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
592 * \return The location on the var_cache corresponding the the string starting at I
593 */
594static struct var_cache *
595parse_string (GLubyte ** inst, struct var_cache **vc_head,
596 struct arb_program *Program, GLuint * found)
597{
598 GLubyte *i = *inst;
599 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000600 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000601
602 *inst += _mesa_strlen ((char *) i) + 1;
603
604 va = var_cache_find (*vc_head, i);
605
606 if (va) {
607 *found = 1;
608 return va;
609 }
610
611 *found = 0;
612 var_cache_create (&va);
613 va->name = i;
614
615 var_cache_append (vc_head, va);
616
617 return va;
618}
619
620static char *
621parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
622{
623 GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000624 (void) Program;
625
Jouk Jansen40322e12004-04-05 08:50:36 +0000626 *inst += _mesa_strlen ((char *) i) + 1;
627
628 return (char *) i;
629}
630
631/**
Brian Paul05908952004-06-08 15:20:23 +0000632 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000633 */
Brian Paul05908952004-06-08 15:20:23 +0000634static GLint
Jouk Jansen40322e12004-04-05 08:50:36 +0000635parse_sign (GLubyte ** inst)
636{
637 /*return *(*inst)++ != '+'; */
638
639 if (**inst == '-') {
640 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000641 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000642 }
643 else if (**inst == '+') {
644 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000645 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000646 }
647
Brian Paul05908952004-06-08 15:20:23 +0000648 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000649}
650
651/**
652 * parses and returns signed integer
653 */
654static GLint
655parse_integer (GLubyte ** inst, struct arb_program *Program)
656{
657 GLint sign;
658 GLint value;
659
660 /* check if *inst points to '+' or '-'
661 * if yes, grab the sign and increment *inst
662 */
663 sign = parse_sign (inst);
664
665 /* now check if *inst points to 0
666 * if yes, increment the *inst and return the default value
667 */
668 if (**inst == 0) {
669 (*inst)++;
670 return 0;
671 }
672
673 /* parse the integer as you normally would do it */
674 value = _mesa_atoi (parse_string_without_adding (inst, Program));
675
676 /* now, after terminating 0 there is a position
677 * to parse it - parse_position()
678 */
679 Program->Position = parse_position (inst);
680
Brian Paul05908952004-06-08 15:20:23 +0000681 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000682}
683
684/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000685 Accumulate this string of digits, and return them as
686 a large integer represented in floating point (for range).
687 If scale is not NULL, also accumulates a power-of-ten
688 integer scale factor that represents the number of digits
689 in the string.
690*/
691static GLdouble
692parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
693{
694 GLdouble value = 0.0;
695 GLdouble oscale = 1.0;
696
697 if (**inst == 0) { /* this string of digits is empty-- do nothing */
698 (*inst)++;
699 }
700 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000701 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000702 GLubyte digit = *((*inst)++);
703 value = value * 10.0 + (GLint) (digit - '0');
704 oscale *= 10.0;
705 }
706 assert(**inst == 0); /* integer string should end with 0 */
707 (*inst)++; /* skip over terminating 0 */
708 Program->Position = parse_position(inst); /* skip position (from integer) */
709 }
710 if (scale)
711 *scale = oscale;
712 return value;
713}
714
715/**
716 Parse an unsigned floating-point number from this stream of tokenized
717 characters. Example floating-point formats supported:
718 12.34
719 12
720 0.34
721 .34
722 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000723 */
724static GLfloat
725parse_float (GLubyte ** inst, struct arb_program *Program)
726{
Brian Paul1ff8f502005-02-16 15:08:29 +0000727 GLint exponent;
728 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000729
Brian Paul1ff8f502005-02-16 15:08:29 +0000730 whole = parse_float_string(inst, Program, 0);
731 fraction = parse_float_string(inst, Program, &fracScale);
732
733 /* Parse signed exponent */
734 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000735
Brian Paul1ff8f502005-02-16 15:08:29 +0000736 /* Assemble parts of floating-point number: */
737 return (GLfloat) ((whole + fraction / fracScale) *
738 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000739}
740
741
742/**
743 */
744static GLfloat
745parse_signed_float (GLubyte ** inst, struct arb_program *Program)
746{
Brian Paul05908952004-06-08 15:20:23 +0000747 GLint sign = parse_sign (inst);
748 GLfloat value = parse_float (inst, Program);
749 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000750}
751
752/**
753 * This picks out a constant value from the parsed array. The constant vector is r
754 * returned in the *values array, which should be of length 4.
755 *
756 * \param values - The 4 component vector with the constant value in it
757 */
758static GLvoid
759parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
760 GLboolean use)
761{
762 GLuint components, i;
763
764
765 switch (*(*inst)++) {
766 case CONSTANT_SCALAR:
767 if (use == GL_TRUE) {
768 values[0] =
769 values[1] =
770 values[2] = values[3] = parse_float (inst, Program);
771 }
772 else {
773 values[0] =
774 values[1] =
775 values[2] = values[3] = parse_signed_float (inst, Program);
776 }
777
778 break;
779 case CONSTANT_VECTOR:
780 values[0] = values[1] = values[2] = 0;
781 values[3] = 1;
782 components = *(*inst)++;
783 for (i = 0; i < components; i++) {
784 values[i] = parse_signed_float (inst, Program);
785 }
786 break;
787 }
788}
789
790/**
791 * \param offset The offset from the address register that we should
792 * address
793 *
794 * \return 0 on sucess, 1 on error
795 */
796static GLuint
797parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
798 GLint *offset)
799{
800 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000801 return 0;
802}
803
804/**
805 * \param color 0 if color type is primary, 1 if color type is secondary
806 * \return 0 on sucess, 1 on error
807 */
808static GLuint
809parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
810 GLint * color)
811{
Brian Paula6c423d2004-08-25 15:59:48 +0000812 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000813 *color = *(*inst)++ != COLOR_PRIMARY;
814 return 0;
815}
816
817/**
818 * Get an integer corresponding to a generic vertex attribute.
819 *
820 * \return 0 on sucess, 1 on error
821 */
822static GLuint
823parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
824 struct arb_program *Program, GLuint *attrib)
825{
Brian Paulbd997cd2004-07-20 21:12:56 +0000826 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000827
Brian Paulbd997cd2004-07-20 21:12:56 +0000828 if ((i < 0) || (i > MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000829 {
830 _mesa_set_program_error (ctx, Program->Position,
831 "Invalid generic vertex attribute index");
832 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
833
834 return 1;
835 }
836
Brian Paulbd997cd2004-07-20 21:12:56 +0000837 *attrib = (GLuint) i;
838
Jouk Jansen40322e12004-04-05 08:50:36 +0000839 return 0;
840}
841
842
843/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000844 * \param color The index of the color buffer to write into
845 * \return 0 on sucess, 1 on error
846 */
847static GLuint
848parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
849 struct arb_program *Program, GLuint * color)
850{
851 GLint i = parse_integer (inst, Program);
852
853 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
854 _mesa_set_program_error (ctx, Program->Position,
855 "Invalid draw buffer index");
856 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid draw buffer index");
857 return 1;
858 }
859
860 *color = (GLuint) i;
861 return 0;
862}
863
864
865/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000866 * \param coord The texture unit index
867 * \return 0 on sucess, 1 on error
868 */
869static GLuint
870parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
871 struct arb_program *Program, GLuint * coord)
872{
Brian Paulbd997cd2004-07-20 21:12:56 +0000873 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000874
Brian Paula6c423d2004-08-25 15:59:48 +0000875 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000876 _mesa_set_program_error (ctx, Program->Position,
877 "Invalid texture unit index");
878 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
879 return 1;
880 }
881
Brian Paulbd997cd2004-07-20 21:12:56 +0000882 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000883 return 0;
884}
885
886/**
887 * \param coord The weight index
888 * \return 0 on sucess, 1 on error
889 */
890static GLuint
891parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
892 GLint * coord)
893{
894 *coord = parse_integer (inst, Program);
895
896 if ((*coord < 0) || (*coord >= 1)) {
897 _mesa_set_program_error (ctx, Program->Position,
898 "Invalid weight index");
899 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
900 return 1;
901 }
902
903 return 0;
904}
905
906/**
907 * \param coord The clip plane index
908 * \return 0 on sucess, 1 on error
909 */
910static GLuint
911parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
912 struct arb_program *Program, GLint * coord)
913{
914 *coord = parse_integer (inst, Program);
915
916 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
917 _mesa_set_program_error (ctx, Program->Position,
918 "Invalid clip plane index");
919 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
920 return 1;
921 }
922
923 return 0;
924}
925
926
927/**
928 * \return 0 on front face, 1 on back face
929 */
930static GLuint
931parse_face_type (GLubyte ** inst)
932{
933 switch (*(*inst)++) {
934 case FACE_FRONT:
935 return 0;
936
937 case FACE_BACK:
938 return 1;
939 }
940 return 0;
941}
942
943
944/**
945 * Given a matrix and a modifier token on the binary array, return tokens
946 * that _mesa_fetch_state() [program.c] can understand.
947 *
948 * \param matrix - the matrix we are talking about
949 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
950 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
951 * \return 0 on sucess, 1 on failure
952 */
953static GLuint
954parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
955 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
956{
957 GLubyte mat = *(*inst)++;
958
959 *matrix_idx = 0;
960
961 switch (mat) {
962 case MATRIX_MODELVIEW:
963 *matrix = STATE_MODELVIEW;
964 *matrix_idx = parse_integer (inst, Program);
965 if (*matrix_idx > 0) {
966 _mesa_set_program_error (ctx, Program->Position,
967 "ARB_vertex_blend not supported\n");
968 _mesa_error (ctx, GL_INVALID_OPERATION,
969 "ARB_vertex_blend not supported\n");
970 return 1;
971 }
972 break;
973
974 case MATRIX_PROJECTION:
975 *matrix = STATE_PROJECTION;
976 break;
977
978 case MATRIX_MVP:
979 *matrix = STATE_MVP;
980 break;
981
982 case MATRIX_TEXTURE:
983 *matrix = STATE_TEXTURE;
984 *matrix_idx = parse_integer (inst, Program);
985 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
986 _mesa_set_program_error (ctx, Program->Position,
987 "Invalid Texture Unit");
988 _mesa_error (ctx, GL_INVALID_OPERATION,
989 "Invalid Texture Unit: %d", *matrix_idx);
990 return 1;
991 }
992 break;
993
994 /* This is not currently supported (ARB_matrix_palette) */
995 case MATRIX_PALETTE:
996 *matrix_idx = parse_integer (inst, Program);
997 _mesa_set_program_error (ctx, Program->Position,
998 "ARB_matrix_palette not supported\n");
999 _mesa_error (ctx, GL_INVALID_OPERATION,
1000 "ARB_matrix_palette not supported\n");
1001 return 1;
1002 break;
1003
1004 case MATRIX_PROGRAM:
1005 *matrix = STATE_PROGRAM;
1006 *matrix_idx = parse_integer (inst, Program);
1007 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
1008 _mesa_set_program_error (ctx, Program->Position,
1009 "Invalid Program Matrix");
1010 _mesa_error (ctx, GL_INVALID_OPERATION,
1011 "Invalid Program Matrix: %d", *matrix_idx);
1012 return 1;
1013 }
1014 break;
1015 }
1016
1017 switch (*(*inst)++) {
1018 case MATRIX_MODIFIER_IDENTITY:
1019 *matrix_modifier = 0;
1020 break;
1021 case MATRIX_MODIFIER_INVERSE:
1022 *matrix_modifier = STATE_MATRIX_INVERSE;
1023 break;
1024 case MATRIX_MODIFIER_TRANSPOSE:
1025 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1026 break;
1027 case MATRIX_MODIFIER_INVTRANS:
1028 *matrix_modifier = STATE_MATRIX_INVTRANS;
1029 break;
1030 }
1031
1032 return 0;
1033}
1034
1035
1036/**
1037 * This parses a state string (rather, the binary version of it) into
1038 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1039 *
1040 * \param inst - the start in the binary arry to start working from
1041 * \param state_tokens - the storage for the 6-token state description
1042 * \return - 0 on sucess, 1 on error
1043 */
1044static GLuint
1045parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
1046 struct arb_program *Program, GLint * state_tokens)
1047{
1048 switch (*(*inst)++) {
1049 case STATE_MATERIAL_PARSER:
1050 state_tokens[0] = STATE_MATERIAL;
1051 state_tokens[1] = parse_face_type (inst);
1052 switch (*(*inst)++) {
1053 case MATERIAL_AMBIENT:
1054 state_tokens[2] = STATE_AMBIENT;
1055 break;
1056 case MATERIAL_DIFFUSE:
1057 state_tokens[2] = STATE_DIFFUSE;
1058 break;
1059 case MATERIAL_SPECULAR:
1060 state_tokens[2] = STATE_SPECULAR;
1061 break;
1062 case MATERIAL_EMISSION:
1063 state_tokens[2] = STATE_EMISSION;
1064 break;
1065 case MATERIAL_SHININESS:
1066 state_tokens[2] = STATE_SHININESS;
1067 break;
1068 }
1069 break;
1070
1071 case STATE_LIGHT_PARSER:
1072 state_tokens[0] = STATE_LIGHT;
1073 state_tokens[1] = parse_integer (inst, Program);
1074
1075 /* Check the value of state_tokens[1] against the # of lights */
1076 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1077 _mesa_set_program_error (ctx, Program->Position,
1078 "Invalid Light Number");
1079 _mesa_error (ctx, GL_INVALID_OPERATION,
1080 "Invalid Light Number: %d", state_tokens[1]);
1081 return 1;
1082 }
1083
1084 switch (*(*inst)++) {
1085 case LIGHT_AMBIENT:
1086 state_tokens[2] = STATE_AMBIENT;
1087 break;
1088 case LIGHT_DIFFUSE:
1089 state_tokens[2] = STATE_DIFFUSE;
1090 break;
1091 case LIGHT_SPECULAR:
1092 state_tokens[2] = STATE_SPECULAR;
1093 break;
1094 case LIGHT_POSITION:
1095 state_tokens[2] = STATE_POSITION;
1096 break;
1097 case LIGHT_ATTENUATION:
1098 state_tokens[2] = STATE_ATTENUATION;
1099 break;
1100 case LIGHT_HALF:
1101 state_tokens[2] = STATE_HALF;
1102 break;
1103 case LIGHT_SPOT_DIRECTION:
1104 state_tokens[2] = STATE_SPOT_DIRECTION;
1105 break;
1106 }
1107 break;
1108
1109 case STATE_LIGHT_MODEL:
1110 switch (*(*inst)++) {
1111 case LIGHT_MODEL_AMBIENT:
1112 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1113 break;
1114 case LIGHT_MODEL_SCENECOLOR:
1115 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1116 state_tokens[1] = parse_face_type (inst);
1117 break;
1118 }
1119 break;
1120
1121 case STATE_LIGHT_PROD:
1122 state_tokens[0] = STATE_LIGHTPROD;
1123 state_tokens[1] = parse_integer (inst, Program);
1124
1125 /* Check the value of state_tokens[1] against the # of lights */
1126 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1127 _mesa_set_program_error (ctx, Program->Position,
1128 "Invalid Light Number");
1129 _mesa_error (ctx, GL_INVALID_OPERATION,
1130 "Invalid Light Number: %d", state_tokens[1]);
1131 return 1;
1132 }
1133
1134 state_tokens[2] = parse_face_type (inst);
1135 switch (*(*inst)++) {
1136 case LIGHT_PROD_AMBIENT:
1137 state_tokens[3] = STATE_AMBIENT;
1138 break;
1139 case LIGHT_PROD_DIFFUSE:
1140 state_tokens[3] = STATE_DIFFUSE;
1141 break;
1142 case LIGHT_PROD_SPECULAR:
1143 state_tokens[3] = STATE_SPECULAR;
1144 break;
1145 }
1146 break;
1147
1148
1149 case STATE_FOG:
1150 switch (*(*inst)++) {
1151 case FOG_COLOR:
1152 state_tokens[0] = STATE_FOG_COLOR;
1153 break;
1154 case FOG_PARAMS:
1155 state_tokens[0] = STATE_FOG_PARAMS;
1156 break;
1157 }
1158 break;
1159
1160 case STATE_TEX_ENV:
1161 state_tokens[1] = parse_integer (inst, Program);
1162 switch (*(*inst)++) {
1163 case TEX_ENV_COLOR:
1164 state_tokens[0] = STATE_TEXENV_COLOR;
1165 break;
1166 }
1167 break;
1168
1169 case STATE_TEX_GEN:
1170 {
1171 GLuint type, coord;
1172
1173 state_tokens[0] = STATE_TEXGEN;
1174 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1175
1176 if (parse_texcoord_num (ctx, inst, Program, &coord))
1177 return 1;
1178 state_tokens[1] = coord;
1179
1180 /* EYE or OBJECT */
1181 type = *(*inst++);
1182
1183 /* 0 - s, 1 - t, 2 - r, 3 - q */
1184 coord = *(*inst++);
1185
1186 if (type == TEX_GEN_EYE) {
1187 switch (coord) {
1188 case COMPONENT_X:
1189 state_tokens[2] = STATE_TEXGEN_EYE_S;
1190 break;
1191 case COMPONENT_Y:
1192 state_tokens[2] = STATE_TEXGEN_EYE_T;
1193 break;
1194 case COMPONENT_Z:
1195 state_tokens[2] = STATE_TEXGEN_EYE_R;
1196 break;
1197 case COMPONENT_W:
1198 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1199 break;
1200 }
1201 }
1202 else {
1203 switch (coord) {
1204 case COMPONENT_X:
1205 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1206 break;
1207 case COMPONENT_Y:
1208 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1209 break;
1210 case COMPONENT_Z:
1211 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1212 break;
1213 case COMPONENT_W:
1214 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1215 break;
1216 }
1217 }
1218 }
1219 break;
1220
1221 case STATE_DEPTH:
1222 switch (*(*inst)++) {
1223 case DEPTH_RANGE:
1224 state_tokens[0] = STATE_DEPTH_RANGE;
1225 break;
1226 }
1227 break;
1228
1229 case STATE_CLIP_PLANE:
1230 state_tokens[0] = STATE_CLIPPLANE;
1231 state_tokens[1] = parse_integer (inst, Program);
1232 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
1233 return 1;
1234 break;
1235
1236 case STATE_POINT:
1237 switch (*(*inst++)) {
1238 case POINT_SIZE:
1239 state_tokens[0] = STATE_POINT_SIZE;
1240 break;
1241
1242 case POINT_ATTENUATION:
1243 state_tokens[0] = STATE_POINT_ATTENUATION;
1244 break;
1245 }
1246 break;
1247
1248 /* XXX: I think this is the correct format for a matrix row */
1249 case STATE_MATRIX_ROWS:
1250 state_tokens[0] = STATE_MATRIX;
1251 if (parse_matrix
1252 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
1253 &state_tokens[5]))
1254 return 1;
1255
1256 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
1257
1258 if ((**inst) != 0) { /* Either the last row, 0 */
1259 state_tokens[4] = parse_integer (inst, Program);
1260 if (state_tokens[4] < state_tokens[3]) {
1261 _mesa_set_program_error (ctx, Program->Position,
1262 "Second matrix index less than the first");
1263 _mesa_error (ctx, GL_INVALID_OPERATION,
1264 "Second matrix index (%d) less than the first (%d)",
1265 state_tokens[4], state_tokens[3]);
1266 return 1;
1267 }
1268 }
1269 else {
1270 state_tokens[4] = state_tokens[3];
1271 (*inst)++;
1272 }
1273 break;
1274 }
1275
1276 return 0;
1277}
1278
1279/**
1280 * This parses a state string (rather, the binary version of it) into
1281 * a 6-token similar for the state fetching code in program.c
1282 *
1283 * One might ask, why fetch these parameters into just like you fetch
1284 * state when they are already stored in other places?
1285 *
1286 * Because of array offsets -> We can stick env/local parameters in the
1287 * middle of a parameter array and then index someplace into the array
1288 * when we execute.
1289 *
1290 * One optimization might be to only do this for the cases where the
1291 * env/local parameters end up inside of an array, and leave the
1292 * single parameters (or arrays of pure env/local pareameters) in their
1293 * respective register files.
1294 *
1295 * For ENV parameters, the format is:
1296 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1297 * state_tokens[1] = STATE_ENV
1298 * state_tokens[2] = the parameter index
1299 *
1300 * for LOCAL parameters, the format is:
1301 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1302 * state_tokens[1] = STATE_LOCAL
1303 * state_tokens[2] = the parameter index
1304 *
1305 * \param inst - the start in the binary arry to start working from
1306 * \param state_tokens - the storage for the 6-token state description
1307 * \return - 0 on sucess, 1 on failure
1308 */
1309static GLuint
1310parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
1311 struct arb_program *Program, GLint * state_tokens)
1312{
1313 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1314 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1315 else
1316 state_tokens[0] = STATE_VERTEX_PROGRAM;
1317
1318
1319 switch (*(*inst)++) {
1320 case PROGRAM_PARAM_ENV:
1321 state_tokens[1] = STATE_ENV;
1322 state_tokens[2] = parse_integer (inst, Program);
1323
1324 /* Check state_tokens[2] against the number of ENV parameters available */
1325 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001326 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001327 ||
1328 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001329 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001330 _mesa_set_program_error (ctx, Program->Position,
1331 "Invalid Program Env Parameter");
1332 _mesa_error (ctx, GL_INVALID_OPERATION,
1333 "Invalid Program Env Parameter: %d",
1334 state_tokens[2]);
1335 return 1;
1336 }
1337
1338 break;
1339
1340 case PROGRAM_PARAM_LOCAL:
1341 state_tokens[1] = STATE_LOCAL;
1342 state_tokens[2] = parse_integer (inst, Program);
1343
1344 /* Check state_tokens[2] against the number of LOCAL parameters available */
1345 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001346 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001347 ||
1348 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001349 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001350 _mesa_set_program_error (ctx, Program->Position,
1351 "Invalid Program Local Parameter");
1352 _mesa_error (ctx, GL_INVALID_OPERATION,
1353 "Invalid Program Local Parameter: %d",
1354 state_tokens[2]);
1355 return 1;
1356 }
1357 break;
1358 }
1359
1360 return 0;
1361}
1362
1363/**
1364 * For ARB_vertex_program, programs are not allowed to use both an explicit
1365 * vertex attribute and a generic vertex attribute corresponding to the same
1366 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1367 *
1368 * This will walk our var_cache and make sure that nobody does anything fishy.
1369 *
1370 * \return 0 on sucess, 1 on error
1371 */
1372static GLuint
1373generic_attrib_check(struct var_cache *vc_head)
1374{
1375 int a;
1376 struct var_cache *curr;
1377 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1378 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1379
1380 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1381 explicitAttrib[a] = GL_FALSE;
1382 genericAttrib[a] = GL_FALSE;
1383 }
1384
1385 curr = vc_head;
1386 while (curr) {
1387 if (curr->type == vt_attrib) {
1388 if (curr->attrib_is_generic)
Brian Paul18e7c5c2005-10-30 21:46:00 +00001389 genericAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001390 else
Brian Paul18e7c5c2005-10-30 21:46:00 +00001391 explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001392 }
1393
1394 curr = curr->next;
1395 }
1396
1397 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1398 if ((explicitAttrib[a]) && (genericAttrib[a]))
1399 return 1;
1400 }
1401
1402 return 0;
1403}
1404
1405/**
1406 * This will handle the binding side of an ATTRIB var declaration
1407 *
Brian Paul18e7c5c2005-10-30 21:46:00 +00001408 * \param inputReg returns the input register index, one of the
1409 * VERT_ATTRIB_* or FRAG_ATTRIB_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001410 * \return returns 0 on sucess, 1 on error
Jouk Jansen40322e12004-04-05 08:50:36 +00001411 */
1412static GLuint
Brian Paul18e7c5c2005-10-30 21:46:00 +00001413parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
1414 struct arb_program *Program,
1415 GLuint *inputReg, GLuint *is_generic)
Jouk Jansen40322e12004-04-05 08:50:36 +00001416{
Jouk Jansen40322e12004-04-05 08:50:36 +00001417 GLint err = 0;
1418
1419 *is_generic = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001420
Jouk Jansen40322e12004-04-05 08:50:36 +00001421 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1422 switch (*(*inst)++) {
1423 case FRAGMENT_ATTRIB_COLOR:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001424 {
1425 GLint coord;
1426 err = parse_color_type (ctx, inst, Program, &coord);
1427 *inputReg = FRAG_ATTRIB_COL0 + coord;
1428 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001429 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001430 case FRAGMENT_ATTRIB_TEXCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001431 {
1432 GLuint texcoord;
1433 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1434 *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
1435 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001436 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001437 case FRAGMENT_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001438 *inputReg = FRAG_ATTRIB_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001439 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001440 case FRAGMENT_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001441 *inputReg = FRAG_ATTRIB_WPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001442 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001443 default:
1444 err = 1;
1445 break;
1446 }
1447 }
1448 else {
1449 switch (*(*inst)++) {
1450 case VERTEX_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001451 *inputReg = VERT_ATTRIB_POS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001452 break;
1453
1454 case VERTEX_ATTRIB_WEIGHT:
1455 {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001456 const char *msg = "ARB_vertex_blend not supported";
Jouk Jansen40322e12004-04-05 08:50:36 +00001457 GLint weight;
Jouk Jansen40322e12004-04-05 08:50:36 +00001458 err = parse_weight_num (ctx, inst, Program, &weight);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001459 *inputReg = VERT_ATTRIB_WEIGHT;
1460 _mesa_set_program_error(ctx, Program->Position, msg);
1461 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001462 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001463 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001464
1465 case VERTEX_ATTRIB_NORMAL:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001466 *inputReg = VERT_ATTRIB_NORMAL;
Jouk Jansen40322e12004-04-05 08:50:36 +00001467 break;
1468
1469 case VERTEX_ATTRIB_COLOR:
1470 {
1471 GLint color;
Jouk Jansen40322e12004-04-05 08:50:36 +00001472 err = parse_color_type (ctx, inst, Program, &color);
1473 if (color) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001474 *inputReg = VERT_ATTRIB_COLOR1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001475 }
1476 else {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001477 *inputReg = VERT_ATTRIB_COLOR0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001478 }
1479 }
1480 break;
1481
1482 case VERTEX_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001483 *inputReg = VERT_ATTRIB_FOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00001484 break;
1485
1486 case VERTEX_ATTRIB_TEXCOORD:
1487 {
1488 GLuint unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001489 err = parse_texcoord_num (ctx, inst, Program, &unit);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001490 *inputReg = VERT_ATTRIB_TEX0 + unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001491 }
1492 break;
1493
Jouk Jansen40322e12004-04-05 08:50:36 +00001494 case VERTEX_ATTRIB_MATRIXINDEX:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001495 /* Not supported at this time */
1496 {
1497 const char *msg = "ARB_palette_matrix not supported";
1498 parse_integer (inst, Program);
1499 _mesa_set_program_error (ctx, Program->Position, msg);
1500 _mesa_error (ctx, GL_INVALID_OPERATION, msg);
1501 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001502 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001503
1504 case VERTEX_ATTRIB_GENERIC:
1505 {
1506 GLuint attrib;
Jouk Jansen40322e12004-04-05 08:50:36 +00001507 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
1508 *is_generic = 1;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001509 *inputReg = attrib;
Jouk Jansen40322e12004-04-05 08:50:36 +00001510 }
1511 }
1512 break;
1513
1514 default:
1515 err = 1;
1516 break;
1517 }
1518 }
1519
1520 /* Can this even happen? */
1521 if (err) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001522 const char *msg = "Bad attribute binding";
1523 _mesa_set_program_error(ctx, Program->Position, msg);
1524 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001525 }
1526
Brian Paul18e7c5c2005-10-30 21:46:00 +00001527 Program->InputsRead |= (1 << *inputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001528
1529 return err;
1530}
1531
Brian Paul7aebaf32005-10-30 21:23:23 +00001532
Jouk Jansen40322e12004-04-05 08:50:36 +00001533/**
1534 * This translates between a binary token for an output variable type
1535 * and the mesa token for the same thing.
1536 *
Brian Paul7aebaf32005-10-30 21:23:23 +00001537 * \param inst The parsed tokens
1538 * \param outputReg Returned index/number of the output register,
Brian Paul90ebb582005-11-02 18:06:12 +00001539 * one of the VERT_RESULT_* or FRAG_RESULT_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001540 */
1541static GLuint
Brian Paul7aebaf32005-10-30 21:23:23 +00001542parse_result_binding(GLcontext *ctx, GLubyte **inst,
1543 GLuint *outputReg, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00001544{
Brian Paul7aebaf32005-10-30 21:23:23 +00001545 const GLubyte token = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001546
Brian Paul7aebaf32005-10-30 21:23:23 +00001547 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001548 case FRAGMENT_RESULT_COLOR:
Jouk Jansen40322e12004-04-05 08:50:36 +00001549 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001550 GLuint out_color;
1551
Brian Paulbe76b7f2004-10-04 14:40:05 +00001552 /* This gets result of the color buffer we're supposed to
Brian Paul7aebaf32005-10-30 21:23:23 +00001553 * draw into. This pertains to GL_ARB_draw_buffers.
Brian Paulbe76b7f2004-10-04 14:40:05 +00001554 */
1555 parse_output_color_num(ctx, inst, Program, &out_color);
Brian Paul7aebaf32005-10-30 21:23:23 +00001556 ASSERT(out_color < MAX_DRAW_BUFFERS);
Brian Paul90ebb582005-11-02 18:06:12 +00001557 *outputReg = FRAG_RESULT_COLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001558 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001559 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001560 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1561 *outputReg = VERT_RESULT_HPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001562 }
1563 break;
1564
1565 case FRAGMENT_RESULT_DEPTH:
Jouk Jansen40322e12004-04-05 08:50:36 +00001566 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001567 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
Brian Paul90ebb582005-11-02 18:06:12 +00001568 *outputReg = FRAG_RESULT_DEPR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001569 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001570 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001571 /* for vtx programs, this is VERTEX_RESULT_COLOR */
Jouk Jansen40322e12004-04-05 08:50:36 +00001572 GLint color_type;
1573 GLuint face_type = parse_face_type(inst);
Brian Paul7aebaf32005-10-30 21:23:23 +00001574 GLint err = parse_color_type(ctx, inst, Program, &color_type);
1575 if (err)
1576 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001577
Jouk Jansen40322e12004-04-05 08:50:36 +00001578 if (face_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001579 /* back face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001580 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001581 *outputReg = VERT_RESULT_BFC1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001582 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001583 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001584 *outputReg = VERT_RESULT_BFC0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001585 }
1586 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001587 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001588 /* front face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001589 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001590 *outputReg = VERT_RESULT_COL1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001591 }
1592 /* primary color */
1593 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001594 *outputReg = VERT_RESULT_COL0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001595 }
1596 }
1597 }
1598 break;
1599
1600 case VERTEX_RESULT_FOGCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001601 *outputReg = VERT_RESULT_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001602 break;
1603
1604 case VERTEX_RESULT_POINTSIZE:
Brian Paul7aebaf32005-10-30 21:23:23 +00001605 *outputReg = VERT_RESULT_PSIZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00001606 break;
1607
1608 case VERTEX_RESULT_TEXCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001609 {
1610 GLuint unit;
1611 if (parse_texcoord_num (ctx, inst, Program, &unit))
1612 return 1;
1613 *outputReg = VERT_RESULT_TEX0 + unit;
1614 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001615 break;
1616 }
1617
Brian Paul7aebaf32005-10-30 21:23:23 +00001618 Program->OutputsWritten |= (1 << *outputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001619
1620 return 0;
1621}
1622
Brian Paul7aebaf32005-10-30 21:23:23 +00001623
Jouk Jansen40322e12004-04-05 08:50:36 +00001624/**
1625 * This handles the declaration of ATTRIB variables
1626 *
1627 * XXX: Still needs
1628 * parse_vert_attrib_binding(), or something like that
1629 *
1630 * \return 0 on sucess, 1 on error
1631 */
1632static GLint
1633parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1634 struct arb_program *Program)
1635{
1636 GLuint found;
1637 char *error_msg;
1638 struct var_cache *attrib_var;
1639
1640 attrib_var = parse_string (inst, vc_head, Program, &found);
1641 Program->Position = parse_position (inst);
1642 if (found) {
1643 error_msg = (char *)
1644 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1645 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1646 attrib_var->name);
1647
1648 _mesa_set_program_error (ctx, Program->Position, error_msg);
1649 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1650
1651 _mesa_free (error_msg);
1652 return 1;
1653 }
1654
1655 attrib_var->type = vt_attrib;
1656
Brian Paul7aebaf32005-10-30 21:23:23 +00001657 if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
Brian Paul7aebaf32005-10-30 21:23:23 +00001658 &attrib_var->attrib_is_generic))
1659 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001660
Brian Paul7aebaf32005-10-30 21:23:23 +00001661 if (generic_attrib_check(*vc_head)) {
1662 _mesa_set_program_error(ctx, Program->Position,
1663 "Cannot use both a generic vertex attribute "
1664 "and a specific attribute of the same type");
1665 _mesa_error(ctx, GL_INVALID_OPERATION,
1666 "Cannot use both a generic vertex attribute and a specific "
1667 "attribute of the same type");
1668 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001669 }
1670
1671 Program->Base.NumAttributes++;
1672 return 0;
1673}
1674
1675/**
1676 * \param use -- TRUE if we're called when declaring implicit parameters,
1677 * FALSE if we're declaraing variables. This has to do with
1678 * if we get a signed or unsigned float for scalar constants
1679 */
1680static GLuint
1681parse_param_elements (GLcontext * ctx, GLubyte ** inst,
1682 struct var_cache *param_var,
1683 struct arb_program *Program, GLboolean use)
1684{
1685 GLint idx;
Brian Paul7aebaf32005-10-30 21:23:23 +00001686 GLuint err = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001687 GLint state_tokens[6];
1688 GLfloat const_values[4];
1689
Jouk Jansen40322e12004-04-05 08:50:36 +00001690 switch (*(*inst)++) {
1691 case PARAM_STATE_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001692 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1693 return 1;
1694
1695 /* If we adding STATE_MATRIX that has multiple rows, we need to
1696 * unroll it and call _mesa_add_state_reference() for each row
1697 */
1698 if ((state_tokens[0] == STATE_MATRIX)
1699 && (state_tokens[3] != state_tokens[4])) {
1700 GLint row;
1701 GLint first_row = state_tokens[3];
1702 GLint last_row = state_tokens[4];
1703
1704 for (row = first_row; row <= last_row; row++) {
1705 state_tokens[3] = state_tokens[4] = row;
1706
1707 idx =
1708 _mesa_add_state_reference (Program->Parameters,
1709 state_tokens);
1710 if (param_var->param_binding_begin == ~0U)
1711 param_var->param_binding_begin = idx;
1712 param_var->param_binding_length++;
1713 Program->Base.NumParameters++;
1714 }
1715 }
1716 else {
1717 idx =
1718 _mesa_add_state_reference (Program->Parameters, state_tokens);
1719 if (param_var->param_binding_begin == ~0U)
1720 param_var->param_binding_begin = idx;
1721 param_var->param_binding_length++;
1722 Program->Base.NumParameters++;
1723 }
1724 break;
1725
1726 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001727 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1728 return 1;
1729 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
1730 if (param_var->param_binding_begin == ~0U)
1731 param_var->param_binding_begin = idx;
1732 param_var->param_binding_length++;
1733 Program->Base.NumParameters++;
1734
1735 /* Check if there is more: 0 -> we're done, else its an integer */
1736 if (**inst) {
1737 GLuint out_of_range, new_idx;
1738 GLuint start_idx = state_tokens[2] + 1;
1739 GLuint end_idx = parse_integer (inst, Program);
1740
1741 out_of_range = 0;
1742 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1743 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001744 && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001745 || ((state_tokens[1] == STATE_LOCAL)
1746 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001747 ctx->Const.FragmentProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001748 out_of_range = 1;
1749 }
1750 else {
1751 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001752 && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001753 || ((state_tokens[1] == STATE_LOCAL)
1754 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001755 ctx->Const.VertexProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001756 out_of_range = 1;
1757 }
1758 if (out_of_range) {
1759 _mesa_set_program_error (ctx, Program->Position,
1760 "Invalid Program Parameter");
1761 _mesa_error (ctx, GL_INVALID_OPERATION,
1762 "Invalid Program Parameter: %d", end_idx);
1763 return 1;
1764 }
1765
1766 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1767 state_tokens[2] = new_idx;
1768 idx =
1769 _mesa_add_state_reference (Program->Parameters,
1770 state_tokens);
1771 param_var->param_binding_length++;
1772 Program->Base.NumParameters++;
1773 }
1774 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001775 else {
1776 (*inst)++;
1777 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001778 break;
1779
1780 case PARAM_CONSTANT:
1781 parse_constant (inst, const_values, Program, use);
1782 idx =
1783 _mesa_add_named_constant (Program->Parameters,
1784 (char *) param_var->name, const_values);
1785 if (param_var->param_binding_begin == ~0U)
1786 param_var->param_binding_begin = idx;
1787 param_var->param_binding_length++;
1788 Program->Base.NumParameters++;
1789 break;
1790
1791 default:
Brian Paul7aebaf32005-10-30 21:23:23 +00001792 _mesa_set_program_error(ctx, Program->Position,
1793 "Unexpected token in parse_param_elements()");
1794 _mesa_error(ctx, GL_INVALID_OPERATION,
1795 "Unexpected token in parse_param_elements()");
Jouk Jansen40322e12004-04-05 08:50:36 +00001796 return 1;
1797 }
1798
1799 /* Make sure we haven't blown past our parameter limits */
1800 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1801 (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001802 ctx->Const.VertexProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001803 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1804 && (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001805 ctx->Const.FragmentProgram.MaxLocalParams))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001806 _mesa_set_program_error (ctx, Program->Position,
1807 "Too many parameter variables");
1808 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1809 return 1;
1810 }
1811
1812 return err;
1813}
1814
Brian Paul7aebaf32005-10-30 21:23:23 +00001815
Jouk Jansen40322e12004-04-05 08:50:36 +00001816/**
1817 * This picks out PARAM program parameter bindings.
1818 *
1819 * XXX: This needs to be stressed & tested
1820 *
1821 * \return 0 on sucess, 1 on error
1822 */
1823static GLuint
1824parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1825 struct arb_program *Program)
1826{
Brian Paulbd997cd2004-07-20 21:12:56 +00001827 GLuint found, err;
1828 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001829 struct var_cache *param_var;
1830
1831 err = 0;
1832 param_var = parse_string (inst, vc_head, Program, &found);
1833 Program->Position = parse_position (inst);
1834
1835 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001836 char *error_msg = (char *)
1837 _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
Jouk Jansen40322e12004-04-05 08:50:36 +00001838 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1839 param_var->name);
1840
1841 _mesa_set_program_error (ctx, Program->Position, error_msg);
1842 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1843
1844 _mesa_free (error_msg);
1845 return 1;
1846 }
1847
1848 specified_length = parse_integer (inst, Program);
1849
1850 if (specified_length < 0) {
1851 _mesa_set_program_error (ctx, Program->Position,
1852 "Negative parameter array length");
1853 _mesa_error (ctx, GL_INVALID_OPERATION,
1854 "Negative parameter array length: %d", specified_length);
1855 return 1;
1856 }
1857
1858 param_var->type = vt_param;
1859 param_var->param_binding_length = 0;
1860
1861 /* Right now, everything is shoved into the main state register file.
1862 *
1863 * In the future, it would be nice to leave things ENV/LOCAL params
1864 * in their respective register files, if possible
1865 */
1866 param_var->param_binding_type = PROGRAM_STATE_VAR;
1867
1868 /* Remember to:
1869 * * - add each guy to the parameter list
1870 * * - increment the param_var->param_binding_len
1871 * * - store the param_var->param_binding_begin for the first one
1872 * * - compare the actual len to the specified len at the end
1873 */
1874 while (**inst != PARAM_NULL) {
1875 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1876 return 1;
1877 }
1878
1879 /* Test array length here! */
1880 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001881 if (specified_length != (int)param_var->param_binding_length) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001882 const char *msg
1883 = "Declared parameter array length does not match parameter list";
1884 _mesa_set_program_error(ctx, Program->Position, msg);
1885 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001886 }
1887 }
1888
1889 (*inst)++;
1890
1891 return 0;
1892}
1893
1894/**
1895 *
1896 */
1897static GLuint
1898parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1899 struct arb_program *Program, struct var_cache **new_var)
1900{
1901 struct var_cache *param_var;
1902
1903 /* First, insert a dummy entry into the var_cache */
1904 var_cache_create (&param_var);
1905 param_var->name = (GLubyte *) _mesa_strdup (" ");
1906 param_var->type = vt_param;
1907
1908 param_var->param_binding_length = 0;
1909 /* Don't fill in binding_begin; We use the default value of -1
1910 * to tell if its already initialized, elsewhere.
1911 *
1912 * param_var->param_binding_begin = 0;
1913 */
1914 param_var->param_binding_type = PROGRAM_STATE_VAR;
1915
1916 var_cache_append (vc_head, param_var);
1917
1918 /* Then fill it with juicy parameter goodness */
1919 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1920 return 1;
1921
1922 *new_var = param_var;
1923
1924 return 0;
1925}
1926
1927
1928/**
1929 * This handles the declaration of TEMP variables
1930 *
1931 * \return 0 on sucess, 1 on error
1932 */
1933static GLuint
1934parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1935 struct arb_program *Program)
1936{
1937 GLuint found;
1938 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00001939
1940 while (**inst != 0) {
1941 temp_var = parse_string (inst, vc_head, Program, &found);
1942 Program->Position = parse_position (inst);
1943 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001944 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001945 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
1946 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1947 temp_var->name);
1948
1949 _mesa_set_program_error (ctx, Program->Position, error_msg);
1950 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1951
1952 _mesa_free (error_msg);
1953 return 1;
1954 }
1955
1956 temp_var->type = vt_temp;
1957
1958 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1959 (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001960 ctx->Const.FragmentProgram.MaxTemps))
Jouk Jansen40322e12004-04-05 08:50:36 +00001961 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
1962 && (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001963 ctx->Const.VertexProgram.MaxTemps))) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001964 _mesa_set_program_error (ctx, Program->Position,
1965 "Too many TEMP variables declared");
1966 _mesa_error (ctx, GL_INVALID_OPERATION,
1967 "Too many TEMP variables declared");
1968 return 1;
1969 }
1970
1971 temp_var->temp_binding = Program->Base.NumTemporaries;
1972 Program->Base.NumTemporaries++;
1973 }
1974 (*inst)++;
1975
1976 return 0;
1977}
1978
1979/**
1980 * This handles variables of the OUTPUT variety
1981 *
1982 * \return 0 on sucess, 1 on error
1983 */
1984static GLuint
1985parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1986 struct arb_program *Program)
1987{
1988 GLuint found;
1989 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00001990 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00001991
1992 output_var = parse_string (inst, vc_head, Program, &found);
1993 Program->Position = parse_position (inst);
1994 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001995 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001996 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
1997 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1998 output_var->name);
1999
2000 _mesa_set_program_error (ctx, Program->Position, error_msg);
2001 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2002
2003 _mesa_free (error_msg);
2004 return 1;
2005 }
2006
2007 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002008
2009 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2010 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002011}
2012
2013/**
2014 * This handles variables of the ALIAS kind
2015 *
2016 * \return 0 on sucess, 1 on error
2017 */
2018static GLuint
2019parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2020 struct arb_program *Program)
2021{
2022 GLuint found;
2023 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002024
2025 temp_var = parse_string (inst, vc_head, Program, &found);
2026 Program->Position = parse_position (inst);
2027
2028 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002029 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002030 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2031 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2032 temp_var->name);
2033
2034 _mesa_set_program_error (ctx, Program->Position, error_msg);
2035 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2036
2037 _mesa_free (error_msg);
2038 return 1;
2039 }
2040
2041 temp_var->type = vt_alias;
2042 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2043 Program->Position = parse_position (inst);
2044
2045 if (!found)
2046 {
Brian Paul7aebaf32005-10-30 21:23:23 +00002047 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002048 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2049 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2050 temp_var->alias_binding->name);
2051
2052 _mesa_set_program_error (ctx, Program->Position, error_msg);
2053 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2054
2055 _mesa_free (error_msg);
2056 return 1;
2057 }
2058
2059 return 0;
2060}
2061
2062/**
2063 * This handles variables of the ADDRESS kind
2064 *
2065 * \return 0 on sucess, 1 on error
2066 */
2067static GLuint
2068parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2069 struct arb_program *Program)
2070{
2071 GLuint found;
2072 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002073
2074 while (**inst != 0) {
2075 temp_var = parse_string (inst, vc_head, Program, &found);
2076 Program->Position = parse_position (inst);
2077 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002078 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002079 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2080 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2081 temp_var->name);
2082
2083 _mesa_set_program_error (ctx, Program->Position, error_msg);
2084 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2085
2086 _mesa_free (error_msg);
2087 return 1;
2088 }
2089
2090 temp_var->type = vt_address;
2091
2092 if (Program->Base.NumAddressRegs >=
Brian Paul05051032005-11-01 04:36:33 +00002093 ctx->Const.VertexProgram.MaxAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002094 const char *msg = "Too many ADDRESS variables declared";
2095 _mesa_set_program_error(ctx, Program->Position, msg);
2096
2097 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002098 return 1;
2099 }
2100
2101 temp_var->address_binding = Program->Base.NumAddressRegs;
2102 Program->Base.NumAddressRegs++;
2103 }
2104 (*inst)++;
2105
2106 return 0;
2107}
2108
2109/**
2110 * Parse a program declaration
2111 *
2112 * \return 0 on sucess, 1 on error
2113 */
2114static GLint
2115parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2116 struct arb_program *Program)
2117{
2118 GLint err = 0;
2119
2120 switch (*(*inst)++) {
2121 case ADDRESS:
2122 err = parse_address (ctx, inst, vc_head, Program);
2123 break;
2124
2125 case ALIAS:
2126 err = parse_alias (ctx, inst, vc_head, Program);
2127 break;
2128
2129 case ATTRIB:
2130 err = parse_attrib (ctx, inst, vc_head, Program);
2131 break;
2132
2133 case OUTPUT:
2134 err = parse_output (ctx, inst, vc_head, Program);
2135 break;
2136
2137 case PARAM:
2138 err = parse_param (ctx, inst, vc_head, Program);
2139 break;
2140
2141 case TEMP:
2142 err = parse_temp (ctx, inst, vc_head, Program);
2143 break;
2144 }
2145
2146 return err;
2147}
2148
2149/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002150 * Handle the parsing out of a masked destination register, either for a
2151 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002152 *
2153 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002154 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002155 * position invariant
2156 *
2157 * \param File - The register file we write to
2158 * \param Index - The register index we write to
2159 * \param WriteMask - The mask controlling which components we write (1->write)
2160 *
2161 * \return 0 on sucess, 1 on error
2162 */
2163static GLuint
2164parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2165 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002166 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002167{
Brian Paul7aebaf32005-10-30 21:23:23 +00002168 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002169 struct var_cache *dst;
2170
2171 /* We either have a result register specified, or a
2172 * variable that may or may not be writable
2173 */
2174 switch (*(*inst)++) {
2175 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002176 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002177 return 1;
2178 *File = PROGRAM_OUTPUT;
2179 break;
2180
2181 case REGISTER_ESTABLISHED_NAME:
2182 dst = parse_string (inst, vc_head, Program, &result);
2183 Program->Position = parse_position (inst);
2184
2185 /* If the name has never been added to our symbol table, we're hosed */
2186 if (!result) {
2187 _mesa_set_program_error (ctx, Program->Position,
2188 "0: Undefined variable");
2189 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2190 dst->name);
2191 return 1;
2192 }
2193
2194 switch (dst->type) {
2195 case vt_output:
2196 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002197 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002198 break;
2199
2200 case vt_temp:
2201 *File = PROGRAM_TEMPORARY;
2202 *Index = dst->temp_binding;
2203 break;
2204
2205 /* If the var type is not vt_output or vt_temp, no go */
2206 default:
2207 _mesa_set_program_error (ctx, Program->Position,
2208 "Destination register is read only");
2209 _mesa_error (ctx, GL_INVALID_OPERATION,
2210 "Destination register is read only: %s",
2211 dst->name);
2212 return 1;
2213 }
2214 break;
2215
2216 default:
2217 _mesa_set_program_error (ctx, Program->Position,
2218 "Unexpected opcode in parse_masked_dst_reg()");
2219 _mesa_error (ctx, GL_INVALID_OPERATION,
2220 "Unexpected opcode in parse_masked_dst_reg()");
2221 return 1;
2222 }
2223
2224
2225 /* Position invariance test */
2226 /* This test is done now in syntax portion - when position invariance OPTION
2227 is specified, "result.position" rule is disabled so there is no way
2228 to write the position
2229 */
2230 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2231 (*Index == 0)) {
2232 _mesa_set_program_error (ctx, Program->Position,
2233 "Vertex program specified position invariance and wrote vertex position");
2234 _mesa_error (ctx, GL_INVALID_OPERATION,
2235 "Vertex program specified position invariance and wrote vertex position");
2236 }*/
2237
2238 /* And then the mask.
2239 * w,a -> bit 0
2240 * z,b -> bit 1
2241 * y,g -> bit 2
2242 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002243 *
2244 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002245 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002246 tmp = (GLint) *(*inst)++;
2247 *WriteMask = (((tmp>>3) & 0x1) |
2248 ((tmp>>1) & 0x2) |
2249 ((tmp<<1) & 0x4) |
2250 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002251
2252 return 0;
2253}
2254
2255
2256/**
2257 * Handle the parsing of a address register
2258 *
2259 * \param Index - The register index we write to
2260 *
2261 * \return 0 on sucess, 1 on error
2262 */
2263static GLuint
2264parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2265 struct var_cache **vc_head,
2266 struct arb_program *Program, GLint * Index)
2267{
2268 struct var_cache *dst;
2269 GLuint result;
Brian Paula6c423d2004-08-25 15:59:48 +00002270 (void) Index;
Jouk Jansen40322e12004-04-05 08:50:36 +00002271
2272 dst = parse_string (inst, vc_head, Program, &result);
2273 Program->Position = parse_position (inst);
2274
2275 /* If the name has never been added to our symbol table, we're hosed */
2276 if (!result) {
2277 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2278 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2279 dst->name);
2280 return 1;
2281 }
2282
2283 if (dst->type != vt_address) {
2284 _mesa_set_program_error (ctx, Program->Position,
2285 "Variable is not of type ADDRESS");
2286 _mesa_error (ctx, GL_INVALID_OPERATION,
2287 "Variable: %s is not of type ADDRESS", dst->name);
2288 return 1;
2289 }
2290
2291 return 0;
2292}
2293
Brian Paul8e8fa632005-07-01 02:03:33 +00002294#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002295/**
2296 * Handle the parsing out of a masked address register
2297 *
2298 * \param Index - The register index we write to
2299 * \param WriteMask - The mask controlling which components we write (1->write)
2300 *
2301 * \return 0 on sucess, 1 on error
2302 */
2303static GLuint
2304parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2305 struct var_cache **vc_head,
2306 struct arb_program *Program, GLint * Index,
2307 GLboolean * WriteMask)
2308{
2309 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2310 return 1;
2311
2312 /* This should be 0x8 */
2313 (*inst)++;
2314
2315 /* Writemask of .x is implied */
2316 WriteMask[0] = 1;
2317 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2318
2319 return 0;
2320}
Brian Paul8e8fa632005-07-01 02:03:33 +00002321#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002322
2323/**
2324 * Parse out a swizzle mask.
2325 *
Brian Paul32df89e2005-10-29 18:26:43 +00002326 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002327 *
2328 * The len parameter allows us to grab 4 components for a vector
2329 * swizzle, or just 1 component for a scalar src register selection
2330 */
Brian Paul32df89e2005-10-29 18:26:43 +00002331static void
2332parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002333{
Brian Paul32df89e2005-10-29 18:26:43 +00002334 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002335
Brian Paul32df89e2005-10-29 18:26:43 +00002336 for (i = 0; i < 4; i++)
2337 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002338
Brian Paul32df89e2005-10-29 18:26:43 +00002339 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002340 switch (*(*inst)++) {
2341 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002342 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002343 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002344 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002345 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002346 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002347 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002348 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002349 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002350 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002351 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002352 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002353 default:
2354 _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
2355 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002356 }
2357 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002358}
2359
Jouk Jansen40322e12004-04-05 08:50:36 +00002360
Brian Paul32df89e2005-10-29 18:26:43 +00002361/**
2362 * Parse an extended swizzle mask which is a sequence of
2363 * four x/y/z/w/0/1 tokens.
2364 * \return swizzle four swizzle values
2365 * \return negateMask four element bitfield
2366 */
2367static void
2368parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4],
2369 GLubyte *negateMask)
2370{
2371 GLint i;
2372
2373 *negateMask = 0x0;
2374 for (i = 0; i < 4; i++) {
2375 GLubyte swz;
2376 if (parse_sign(inst) == -1)
2377 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002378
2379 swz = *(*inst)++;
2380
2381 switch (swz) {
2382 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002383 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002384 break;
2385 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002386 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002387 break;
2388 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002389 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002390 break;
2391 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002392 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002393 break;
2394 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002395 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002396 break;
2397 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002398 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002399 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002400 default:
2401 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2402 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002403 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002404 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002405}
2406
2407
2408static GLuint
2409parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002410 struct arb_program *Program,
2411 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002412 GLboolean *IsRelOffset )
2413{
2414 struct var_cache *src;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002415 GLuint binding, is_generic, found;
Brian Paulbd997cd2004-07-20 21:12:56 +00002416 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002417
Keith Whitwell7c26b612005-04-21 14:46:57 +00002418 *IsRelOffset = 0;
2419
Jouk Jansen40322e12004-04-05 08:50:36 +00002420 /* And the binding for the src */
2421 switch (*(*inst)++) {
2422 case REGISTER_ATTRIB:
2423 if (parse_attrib_binding
Brian Paul18e7c5c2005-10-30 21:46:00 +00002424 (ctx, inst, Program, &binding, &is_generic))
Jouk Jansen40322e12004-04-05 08:50:36 +00002425 return 1;
2426 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002427 *Index = binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002428
2429 /* We need to insert a dummy variable into the var_cache so we can
2430 * catch generic vertex attrib aliasing errors
2431 */
2432 var_cache_create(&src);
2433 src->type = vt_attrib;
2434 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
Brian Paul18e7c5c2005-10-30 21:46:00 +00002435 src->attrib_binding = binding;
2436 src->attrib_is_generic = is_generic;
Jouk Jansen40322e12004-04-05 08:50:36 +00002437 var_cache_append(vc_head, src);
2438 if (generic_attrib_check(*vc_head)) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002439 const char *msg = "Cannot use both a generic vertex attribute "
2440 "and a specific attribute of the same type";
2441 _mesa_set_program_error (ctx, Program->Position, msg);
2442 _mesa_error (ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002443 return 1;
2444 }
2445 break;
2446
2447 case REGISTER_PARAM:
2448 switch (**inst) {
2449 case PARAM_ARRAY_ELEMENT:
2450 (*inst)++;
2451 src = parse_string (inst, vc_head, Program, &found);
2452 Program->Position = parse_position (inst);
2453
2454 if (!found) {
2455 _mesa_set_program_error (ctx, Program->Position,
2456 "2: Undefined variable");
2457 _mesa_error (ctx, GL_INVALID_OPERATION,
2458 "2: Undefined variable: %s", src->name);
2459 return 1;
2460 }
2461
2462 *File = src->param_binding_type;
2463
2464 switch (*(*inst)++) {
2465 case ARRAY_INDEX_ABSOLUTE:
2466 offset = parse_integer (inst, Program);
2467
2468 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002469 || (offset >= (int)src->param_binding_length)) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002470 _mesa_set_program_error (ctx, Program->Position,
2471 "Index out of range");
2472 _mesa_error (ctx, GL_INVALID_OPERATION,
2473 "Index %d out of range for %s", offset,
2474 src->name);
2475 return 1;
2476 }
2477
2478 *Index = src->param_binding_begin + offset;
2479 break;
2480
2481 case ARRAY_INDEX_RELATIVE:
2482 {
2483 GLint addr_reg_idx, rel_off;
2484
2485 /* First, grab the address regiseter */
2486 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2487 return 1;
2488
2489 /* And the .x */
2490 ((*inst)++);
2491 ((*inst)++);
2492 ((*inst)++);
2493 ((*inst)++);
2494
2495 /* Then the relative offset */
2496 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2497
2498 /* And store it properly */
2499 *Index = src->param_binding_begin + rel_off;
2500 *IsRelOffset = 1;
2501 }
2502 break;
2503 }
2504 break;
2505
2506 default:
Jouk Jansen40322e12004-04-05 08:50:36 +00002507 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2508 return 1;
2509
2510 *File = src->param_binding_type;
2511 *Index = src->param_binding_begin;
2512 break;
2513 }
2514 break;
2515
2516 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002517 src = parse_string (inst, vc_head, Program, &found);
2518 Program->Position = parse_position (inst);
2519
2520 /* If the name has never been added to our symbol table, we're hosed */
2521 if (!found) {
2522 _mesa_set_program_error (ctx, Program->Position,
2523 "3: Undefined variable");
2524 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2525 src->name);
2526 return 1;
2527 }
2528
2529 switch (src->type) {
2530 case vt_attrib:
2531 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002532 *Index = src->attrib_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002533 break;
2534
2535 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2536 case vt_param:
2537 *File = src->param_binding_type;
2538 *Index = src->param_binding_begin;
2539 break;
2540
2541 case vt_temp:
2542 *File = PROGRAM_TEMPORARY;
2543 *Index = src->temp_binding;
2544 break;
2545
2546 /* If the var type is vt_output no go */
2547 default:
2548 _mesa_set_program_error (ctx, Program->Position,
2549 "destination register is read only");
2550 _mesa_error (ctx, GL_INVALID_OPERATION,
2551 "destination register is read only: %s",
2552 src->name);
2553 return 1;
2554 }
2555 break;
2556
2557 default:
2558 _mesa_set_program_error (ctx, Program->Position,
2559 "Unknown token in parse_src_reg");
2560 _mesa_error (ctx, GL_INVALID_OPERATION,
2561 "Unknown token in parse_src_reg");
2562 return 1;
2563 }
2564
2565 return 0;
2566}
2567
2568/**
Brian Paul18e7c5c2005-10-30 21:46:00 +00002569 * Parse fragment program vector source register.
Jouk Jansen40322e12004-04-05 08:50:36 +00002570 */
2571static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00002572parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
2573 struct var_cache **vc_head,
2574 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00002575 struct prog_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002576{
Brian Paul7aebaf32005-10-30 21:23:23 +00002577 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002578 GLint index;
2579 GLboolean negate;
2580 GLubyte swizzle[4];
2581 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002582
Jouk Jansen40322e12004-04-05 08:50:36 +00002583 /* Grab the sign */
Brian Paul32df89e2005-10-29 18:26:43 +00002584 negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002585
2586 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002587 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002588 return 1;
2589
2590 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002591 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002592
Brian Paul32df89e2005-10-29 18:26:43 +00002593 reg->File = file;
2594 reg->Index = index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002595 reg->Abs = 0; /* NV only */
2596 reg->NegateAbs = 0; /* NV only */
Brian Paul32df89e2005-10-29 18:26:43 +00002597 reg->NegateBase = negate;
2598 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00002599 return 0;
2600}
2601
Jouk Jansen40322e12004-04-05 08:50:36 +00002602
Keith Whitwell7c26b612005-04-21 14:46:57 +00002603static GLuint
2604parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
2605 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002606 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002607{
Brian Paul7aebaf32005-10-30 21:23:23 +00002608 GLint mask;
2609 GLuint idx;
2610 enum register_file file;
2611
Keith Whitwell7c26b612005-04-21 14:46:57 +00002612 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002613 return 1;
2614
Keith Whitwell7c26b612005-04-21 14:46:57 +00002615 reg->CondMask = 0; /* NV only */
2616 reg->CondSwizzle = 0; /* NV only */
2617 reg->File = file;
2618 reg->Index = idx;
2619 reg->WriteMask = mask;
2620 return 0;
2621}
2622
2623
Brian Paul7aebaf32005-10-30 21:23:23 +00002624/**
2625 * Parse fragment program scalar src register.
2626 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002627static GLuint
2628parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00002629 struct var_cache **vc_head,
2630 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002631 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002632{
Brian Paul7aebaf32005-10-30 21:23:23 +00002633 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002634 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00002635 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002636 GLubyte Swizzle[4];
2637 GLboolean IsRelOffset;
2638
2639 /* Grab the sign */
2640 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2641
2642 /* And the src reg */
2643 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2644 return 1;
2645
2646 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002647 parse_swizzle_mask(inst, Swizzle, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002648
Keith Whitwell7c26b612005-04-21 14:46:57 +00002649 reg->File = File;
2650 reg->Index = Index;
2651 reg->Abs = 0; /* NV only */
2652 reg->NegateAbs = 0; /* NV only */
2653 reg->NegateBase = Negate;
2654 reg->Swizzle = (Swizzle[0] << 0);
2655
Jouk Jansen40322e12004-04-05 08:50:36 +00002656 return 0;
2657}
2658
Keith Whitwell7c26b612005-04-21 14:46:57 +00002659
Jouk Jansen40322e12004-04-05 08:50:36 +00002660/**
2661 * This is a big mother that handles getting opcodes into the instruction
2662 * and handling the src & dst registers for fragment program instructions
2663 */
2664static GLuint
2665parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2666 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002667 struct prog_instruction *fp)
Jouk Jansen40322e12004-04-05 08:50:36 +00002668{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002669 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002670 GLuint texcoord;
2671 GLubyte instClass, type, code;
2672 GLboolean rel;
2673
Brian Paul7e807512005-11-05 17:10:45 +00002674 _mesa_init_instruction(fp);
Jouk Jansen40322e12004-04-05 08:50:36 +00002675
2676 /* Record the position in the program string for debugging */
2677 fp->StringPos = Program->Position;
2678
2679 /* OP_ALU_INST or OP_TEX_INST */
2680 instClass = *(*inst)++;
2681
2682 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2683 * OP_TEX_{SAMPLE, KIL}
2684 */
2685 type = *(*inst)++;
2686
2687 /* The actual opcode name */
2688 code = *(*inst)++;
2689
2690 /* Increment the correct count */
2691 switch (instClass) {
2692 case OP_ALU_INST:
2693 Program->NumAluInstructions++;
2694 break;
2695 case OP_TEX_INST:
2696 Program->NumTexInstructions++;
2697 break;
2698 }
2699
Jouk Jansen40322e12004-04-05 08:50:36 +00002700 switch (type) {
2701 case OP_ALU_VECTOR:
2702 switch (code) {
2703 case OP_ABS_SAT:
2704 fp->Saturate = 1;
2705 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00002706 fp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002707 break;
2708
2709 case OP_FLR_SAT:
2710 fp->Saturate = 1;
2711 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00002712 fp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00002713 break;
2714
2715 case OP_FRC_SAT:
2716 fp->Saturate = 1;
2717 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00002718 fp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00002719 break;
2720
2721 case OP_LIT_SAT:
2722 fp->Saturate = 1;
2723 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00002724 fp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002725 break;
2726
2727 case OP_MOV_SAT:
2728 fp->Saturate = 1;
2729 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00002730 fp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00002731 break;
2732 }
2733
Keith Whitwell7c26b612005-04-21 14:46:57 +00002734 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002735 return 1;
2736
Keith Whitwell7c26b612005-04-21 14:46:57 +00002737 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002738 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002739 break;
2740
2741 case OP_ALU_SCALAR:
2742 switch (code) {
2743 case OP_COS_SAT:
2744 fp->Saturate = 1;
2745 case OP_COS:
Brian Paul7e807512005-11-05 17:10:45 +00002746 fp->Opcode = OPCODE_COS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002747 break;
2748
2749 case OP_EX2_SAT:
2750 fp->Saturate = 1;
2751 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00002752 fp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002753 break;
2754
2755 case OP_LG2_SAT:
2756 fp->Saturate = 1;
2757 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00002758 fp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002759 break;
2760
2761 case OP_RCP_SAT:
2762 fp->Saturate = 1;
2763 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00002764 fp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002765 break;
2766
2767 case OP_RSQ_SAT:
2768 fp->Saturate = 1;
2769 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00002770 fp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002771 break;
2772
2773 case OP_SIN_SAT:
2774 fp->Saturate = 1;
2775 case OP_SIN:
Brian Paul7e807512005-11-05 17:10:45 +00002776 fp->Opcode = OPCODE_SIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002777 break;
2778
2779 case OP_SCS_SAT:
2780 fp->Saturate = 1;
2781 case OP_SCS:
2782
Brian Paul7e807512005-11-05 17:10:45 +00002783 fp->Opcode = OPCODE_SCS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002784 break;
2785 }
2786
Keith Whitwell7c26b612005-04-21 14:46:57 +00002787 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002788 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002789
2790 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002791 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002792 break;
2793
2794 case OP_ALU_BINSC:
2795 switch (code) {
2796 case OP_POW_SAT:
2797 fp->Saturate = 1;
2798 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00002799 fp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00002800 break;
2801 }
2802
Keith Whitwell7c26b612005-04-21 14:46:57 +00002803 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002804 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002805
Jouk Jansen40322e12004-04-05 08:50:36 +00002806 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002807 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002808 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002809 }
2810 break;
2811
2812
2813 case OP_ALU_BIN:
2814 switch (code) {
2815 case OP_ADD_SAT:
2816 fp->Saturate = 1;
2817 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00002818 fp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002819 break;
2820
2821 case OP_DP3_SAT:
2822 fp->Saturate = 1;
2823 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00002824 fp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00002825 break;
2826
2827 case OP_DP4_SAT:
2828 fp->Saturate = 1;
2829 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00002830 fp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00002831 break;
2832
2833 case OP_DPH_SAT:
2834 fp->Saturate = 1;
2835 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00002836 fp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00002837 break;
2838
2839 case OP_DST_SAT:
2840 fp->Saturate = 1;
2841 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00002842 fp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00002843 break;
2844
2845 case OP_MAX_SAT:
2846 fp->Saturate = 1;
2847 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00002848 fp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002849 break;
2850
2851 case OP_MIN_SAT:
2852 fp->Saturate = 1;
2853 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00002854 fp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002855 break;
2856
2857 case OP_MUL_SAT:
2858 fp->Saturate = 1;
2859 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00002860 fp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00002861 break;
2862
2863 case OP_SGE_SAT:
2864 fp->Saturate = 1;
2865 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00002866 fp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002867 break;
2868
2869 case OP_SLT_SAT:
2870 fp->Saturate = 1;
2871 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00002872 fp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002873 break;
2874
2875 case OP_SUB_SAT:
2876 fp->Saturate = 1;
2877 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00002878 fp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002879 break;
2880
2881 case OP_XPD_SAT:
2882 fp->Saturate = 1;
2883 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00002884 fp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002885 break;
2886 }
2887
Keith Whitwell7c26b612005-04-21 14:46:57 +00002888 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002889 return 1;
2890 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002891 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2892 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002893 }
2894 break;
2895
2896 case OP_ALU_TRI:
2897 switch (code) {
2898 case OP_CMP_SAT:
2899 fp->Saturate = 1;
2900 case OP_CMP:
Brian Paul7e807512005-11-05 17:10:45 +00002901 fp->Opcode = OPCODE_CMP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002902 break;
2903
2904 case OP_LRP_SAT:
2905 fp->Saturate = 1;
2906 case OP_LRP:
Brian Paul7e807512005-11-05 17:10:45 +00002907 fp->Opcode = OPCODE_LRP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002908 break;
2909
2910 case OP_MAD_SAT:
2911 fp->Saturate = 1;
2912 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00002913 fp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002914 break;
2915 }
2916
Keith Whitwell7c26b612005-04-21 14:46:57 +00002917 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002918 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002919
Jouk Jansen40322e12004-04-05 08:50:36 +00002920 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002921 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2922 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002923 }
2924 break;
2925
2926 case OP_ALU_SWZ:
2927 switch (code) {
2928 case OP_SWZ_SAT:
2929 fp->Saturate = 1;
2930 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00002931 fp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002932 break;
2933 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00002934 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002935 return 1;
2936
Keith Whitwell7c26b612005-04-21 14:46:57 +00002937 {
Brian Paul32df89e2005-10-29 18:26:43 +00002938 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002939 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002940 enum register_file file;
2941 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002942
Brian Paul32df89e2005-10-29 18:26:43 +00002943 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002944 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00002945 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
2946 fp->SrcReg[0].File = file;
2947 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00002948 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002949 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
2950 swizzle[1],
2951 swizzle[2],
2952 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00002953 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002954 break;
2955
2956 case OP_TEX_SAMPLE:
2957 switch (code) {
2958 case OP_TEX_SAT:
2959 fp->Saturate = 1;
2960 case OP_TEX:
Brian Paul7e807512005-11-05 17:10:45 +00002961 fp->Opcode = OPCODE_TEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002962 break;
2963
2964 case OP_TXP_SAT:
2965 fp->Saturate = 1;
2966 case OP_TXP:
Brian Paul7e807512005-11-05 17:10:45 +00002967 fp->Opcode = OPCODE_TXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002968 break;
2969
2970 case OP_TXB_SAT:
Jouk Jansen40322e12004-04-05 08:50:36 +00002971 fp->Saturate = 1;
2972 case OP_TXB:
Brian Paul7e807512005-11-05 17:10:45 +00002973 fp->Opcode = OPCODE_TXB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002974 break;
2975 }
2976
Keith Whitwell7c26b612005-04-21 14:46:57 +00002977 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002978 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002979
2980 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002981 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002982
2983 /* texImageUnit */
2984 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
2985 return 1;
2986 fp->TexSrcUnit = texcoord;
2987
2988 /* texTarget */
2989 switch (*(*inst)++) {
2990 case TEXTARGET_1D:
Brian Paul7e807512005-11-05 17:10:45 +00002991 fp->TexSrcTarget = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002992 break;
2993 case TEXTARGET_2D:
Brian Paul7e807512005-11-05 17:10:45 +00002994 fp->TexSrcTarget = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002995 break;
2996 case TEXTARGET_3D:
Brian Paul7e807512005-11-05 17:10:45 +00002997 fp->TexSrcTarget = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002998 break;
2999 case TEXTARGET_RECT:
Brian Paul7e807512005-11-05 17:10:45 +00003000 fp->TexSrcTarget = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003001 break;
3002 case TEXTARGET_CUBE:
Brian Paul7e807512005-11-05 17:10:45 +00003003 fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003004 break;
3005 case TEXTARGET_SHADOW1D:
3006 case TEXTARGET_SHADOW2D:
3007 case TEXTARGET_SHADOWRECT:
3008 /* TODO ARB_fragment_program_shadow code */
3009 break;
3010 }
Brian Paul7e807512005-11-05 17:10:45 +00003011 Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcTarget);
Jouk Jansen40322e12004-04-05 08:50:36 +00003012 break;
3013
3014 case OP_TEX_KIL:
Keith Whitwellc3626a92005-11-01 17:25:49 +00003015 Program->UsesKill = 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003016 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003017 return 1;
Brian Paul7e807512005-11-05 17:10:45 +00003018 fp->Opcode = OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003019 break;
3020 }
3021
3022 return 0;
3023}
3024
Keith Whitwell7c26b612005-04-21 14:46:57 +00003025static GLuint
3026parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
3027 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003028 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003029{
Brian Paul7aebaf32005-10-30 21:23:23 +00003030 GLint mask;
3031 GLuint idx;
3032 enum register_file file;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003033
3034 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3035 return 1;
3036
3037 reg->File = file;
3038 reg->Index = idx;
3039 reg->WriteMask = mask;
3040 return 0;
3041}
3042
3043/**
3044 * Handle the parsing out of a masked address register
3045 *
3046 * \param Index - The register index we write to
3047 * \param WriteMask - The mask controlling which components we write (1->write)
3048 *
3049 * \return 0 on sucess, 1 on error
3050 */
3051static GLuint
3052parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
3053 struct var_cache **vc_head,
3054 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003055 struct prog_dst_register *reg)
Keith Whitwell7c26b612005-04-21 14:46:57 +00003056{
3057 GLint idx;
3058
3059 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3060 return 1;
3061
3062 /* This should be 0x8 */
3063 (*inst)++;
3064
3065 reg->File = PROGRAM_ADDRESS;
3066 reg->Index = idx;
3067
3068 /* Writemask of .x is implied */
3069 reg->WriteMask = 0x1;
3070 return 0;
3071}
3072
3073/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003074 * Parse vertex program vector source register.
Keith Whitwell7c26b612005-04-21 14:46:57 +00003075 */
3076static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00003077parse_vp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
3078 struct var_cache **vc_head,
3079 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00003080 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003081{
Brian Paul7aebaf32005-10-30 21:23:23 +00003082 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00003083 GLint index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003084 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003085 GLubyte swizzle[4];
3086 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003087
3088 /* Grab the sign */
Brian Paul7aebaf32005-10-30 21:23:23 +00003089 negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003090
3091 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00003092 if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003093 return 1;
3094
3095 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003096 parse_swizzle_mask(inst, swizzle, 4);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003097
Brian Paul32df89e2005-10-29 18:26:43 +00003098 reg->File = file;
3099 reg->Index = index;
3100 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
3101 swizzle[2], swizzle[3]);
Brian Paul7e807512005-11-05 17:10:45 +00003102 reg->NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003103 reg->RelAddr = isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003104 return 0;
3105}
3106
3107
3108static GLuint
3109parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00003110 struct var_cache **vc_head,
3111 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003112 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003113{
Brian Paul7aebaf32005-10-30 21:23:23 +00003114 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003115 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003116 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003117 GLubyte Swizzle[4];
3118 GLboolean IsRelOffset;
3119
3120 /* Grab the sign */
3121 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3122
3123 /* And the src reg */
3124 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3125 return 1;
3126
3127 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003128 parse_swizzle_mask(inst, Swizzle, 1);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003129
3130 reg->File = File;
3131 reg->Index = Index;
3132 reg->Swizzle = (Swizzle[0] << 0);
Brian Paul7e807512005-11-05 17:10:45 +00003133 reg->NegateBase = Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003134 reg->RelAddr = IsRelOffset;
3135 return 0;
3136}
3137
3138
Jouk Jansen40322e12004-04-05 08:50:36 +00003139/**
3140 * This is a big mother that handles getting opcodes into the instruction
3141 * and handling the src & dst registers for vertex program instructions
3142 */
3143static GLuint
3144parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3145 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003146 struct prog_instruction *vp)
Jouk Jansen40322e12004-04-05 08:50:36 +00003147{
3148 GLint a;
3149 GLubyte type, code;
3150
3151 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3152 type = *(*inst)++;
3153
3154 /* The actual opcode name */
3155 code = *(*inst)++;
3156
Brian Paul7e807512005-11-05 17:10:45 +00003157 _mesa_init_instruction(vp);
Jouk Jansen40322e12004-04-05 08:50:36 +00003158 /* Record the position in the program string for debugging */
3159 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003160
3161 switch (type) {
3162 /* XXX: */
3163 case OP_ALU_ARL:
Brian Paul7e807512005-11-05 17:10:45 +00003164 vp->Opcode = OPCODE_ARL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003165
3166 /* Remember to set SrcReg.RelAddr; */
3167
3168 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003169 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003170 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003171
Jouk Jansen40322e12004-04-05 08:50:36 +00003172 vp->DstReg.File = PROGRAM_ADDRESS;
3173
3174 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003175 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003176 return 1;
3177
3178 break;
3179
3180 case OP_ALU_VECTOR:
3181 switch (code) {
3182 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00003183 vp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00003184 break;
3185 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00003186 vp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00003187 break;
3188 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00003189 vp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00003190 break;
3191 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00003192 vp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003193 break;
3194 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00003195 vp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00003196 break;
3197 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003198
3199 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003200 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003201
3202 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003203 return 1;
3204 break;
3205
3206 case OP_ALU_SCALAR:
3207 switch (code) {
3208 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00003209 vp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003210 break;
3211 case OP_EXP:
Brian Paul7e807512005-11-05 17:10:45 +00003212 vp->Opcode = OPCODE_EXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003213 break;
3214 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00003215 vp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003216 break;
3217 case OP_LOG:
Brian Paul7e807512005-11-05 17:10:45 +00003218 vp->Opcode = OPCODE_LOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00003219 break;
3220 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00003221 vp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003222 break;
3223 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00003224 vp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003225 break;
3226 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003227 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003228 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003229
3230 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003231 return 1;
3232 break;
3233
3234 case OP_ALU_BINSC:
3235 switch (code) {
3236 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00003237 vp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00003238 break;
3239 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003240 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003241 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003242
Jouk Jansen40322e12004-04-05 08:50:36 +00003243 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003244 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003245 return 1;
3246 }
3247 break;
3248
3249 case OP_ALU_BIN:
3250 switch (code) {
3251 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00003252 vp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003253 break;
3254 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00003255 vp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00003256 break;
3257 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00003258 vp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00003259 break;
3260 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00003261 vp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00003262 break;
3263 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00003264 vp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00003265 break;
3266 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00003267 vp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003268 break;
3269 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00003270 vp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00003271 break;
3272 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00003273 vp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003274 break;
3275 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00003276 vp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003277 break;
3278 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00003279 vp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003280 break;
3281 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00003282 vp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003283 break;
3284 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00003285 vp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003286 break;
3287 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003288 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003289 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003290
Jouk Jansen40322e12004-04-05 08:50:36 +00003291 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003292 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003293 return 1;
3294 }
3295 break;
3296
3297 case OP_ALU_TRI:
3298 switch (code) {
3299 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00003300 vp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003301 break;
3302 }
3303
Keith Whitwell7c26b612005-04-21 14:46:57 +00003304 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003305 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003306
Jouk Jansen40322e12004-04-05 08:50:36 +00003307 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003308 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003309 return 1;
3310 }
3311 break;
3312
3313 case OP_ALU_SWZ:
3314 switch (code) {
3315 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00003316 vp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003317 break;
3318 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003319 {
Brian Paul32df89e2005-10-29 18:26:43 +00003320 GLubyte swizzle[4];
3321 GLubyte negateMask;
3322 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003323 enum register_file file;
3324 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003325
Keith Whitwell7c26b612005-04-21 14:46:57 +00003326 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3327 return 1;
3328
Brian Paul32df89e2005-10-29 18:26:43 +00003329 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003330 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003331 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3332 vp->SrcReg[0].File = file;
3333 vp->SrcReg[0].Index = index;
Brian Paul7e807512005-11-05 17:10:45 +00003334 vp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003335 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3336 swizzle[1],
3337 swizzle[2],
3338 swizzle[3]);
3339 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003340 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003341 break;
3342 }
3343 return 0;
3344}
3345
3346#if DEBUG_PARSING
3347
3348static GLvoid
3349print_state_token (GLint token)
3350{
3351 switch (token) {
3352 case STATE_MATERIAL:
3353 fprintf (stderr, "STATE_MATERIAL ");
3354 break;
3355 case STATE_LIGHT:
3356 fprintf (stderr, "STATE_LIGHT ");
3357 break;
3358
3359 case STATE_LIGHTMODEL_AMBIENT:
3360 fprintf (stderr, "STATE_AMBIENT ");
3361 break;
3362
3363 case STATE_LIGHTMODEL_SCENECOLOR:
3364 fprintf (stderr, "STATE_SCENECOLOR ");
3365 break;
3366
3367 case STATE_LIGHTPROD:
3368 fprintf (stderr, "STATE_LIGHTPROD ");
3369 break;
3370
3371 case STATE_TEXGEN:
3372 fprintf (stderr, "STATE_TEXGEN ");
3373 break;
3374
3375 case STATE_FOG_COLOR:
3376 fprintf (stderr, "STATE_FOG_COLOR ");
3377 break;
3378
3379 case STATE_FOG_PARAMS:
3380 fprintf (stderr, "STATE_FOG_PARAMS ");
3381 break;
3382
3383 case STATE_CLIPPLANE:
3384 fprintf (stderr, "STATE_CLIPPLANE ");
3385 break;
3386
3387 case STATE_POINT_SIZE:
3388 fprintf (stderr, "STATE_POINT_SIZE ");
3389 break;
3390
3391 case STATE_POINT_ATTENUATION:
3392 fprintf (stderr, "STATE_ATTENUATION ");
3393 break;
3394
3395 case STATE_MATRIX:
3396 fprintf (stderr, "STATE_MATRIX ");
3397 break;
3398
3399 case STATE_MODELVIEW:
3400 fprintf (stderr, "STATE_MODELVIEW ");
3401 break;
3402
3403 case STATE_PROJECTION:
3404 fprintf (stderr, "STATE_PROJECTION ");
3405 break;
3406
3407 case STATE_MVP:
3408 fprintf (stderr, "STATE_MVP ");
3409 break;
3410
3411 case STATE_TEXTURE:
3412 fprintf (stderr, "STATE_TEXTURE ");
3413 break;
3414
3415 case STATE_PROGRAM:
3416 fprintf (stderr, "STATE_PROGRAM ");
3417 break;
3418
3419 case STATE_MATRIX_INVERSE:
3420 fprintf (stderr, "STATE_INVERSE ");
3421 break;
3422
3423 case STATE_MATRIX_TRANSPOSE:
3424 fprintf (stderr, "STATE_TRANSPOSE ");
3425 break;
3426
3427 case STATE_MATRIX_INVTRANS:
3428 fprintf (stderr, "STATE_INVTRANS ");
3429 break;
3430
3431 case STATE_AMBIENT:
3432 fprintf (stderr, "STATE_AMBIENT ");
3433 break;
3434
3435 case STATE_DIFFUSE:
3436 fprintf (stderr, "STATE_DIFFUSE ");
3437 break;
3438
3439 case STATE_SPECULAR:
3440 fprintf (stderr, "STATE_SPECULAR ");
3441 break;
3442
3443 case STATE_EMISSION:
3444 fprintf (stderr, "STATE_EMISSION ");
3445 break;
3446
3447 case STATE_SHININESS:
3448 fprintf (stderr, "STATE_SHININESS ");
3449 break;
3450
3451 case STATE_HALF:
3452 fprintf (stderr, "STATE_HALF ");
3453 break;
3454
3455 case STATE_POSITION:
3456 fprintf (stderr, "STATE_POSITION ");
3457 break;
3458
3459 case STATE_ATTENUATION:
3460 fprintf (stderr, "STATE_ATTENUATION ");
3461 break;
3462
3463 case STATE_SPOT_DIRECTION:
3464 fprintf (stderr, "STATE_DIRECTION ");
3465 break;
3466
3467 case STATE_TEXGEN_EYE_S:
3468 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3469 break;
3470
3471 case STATE_TEXGEN_EYE_T:
3472 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3473 break;
3474
3475 case STATE_TEXGEN_EYE_R:
3476 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3477 break;
3478
3479 case STATE_TEXGEN_EYE_Q:
3480 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3481 break;
3482
3483 case STATE_TEXGEN_OBJECT_S:
3484 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3485 break;
3486
3487 case STATE_TEXGEN_OBJECT_T:
3488 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3489 break;
3490
3491 case STATE_TEXGEN_OBJECT_R:
3492 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3493 break;
3494
3495 case STATE_TEXGEN_OBJECT_Q:
3496 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3497 break;
3498
3499 case STATE_TEXENV_COLOR:
3500 fprintf (stderr, "STATE_TEXENV_COLOR ");
3501 break;
3502
3503 case STATE_DEPTH_RANGE:
3504 fprintf (stderr, "STATE_DEPTH_RANGE ");
3505 break;
3506
3507 case STATE_VERTEX_PROGRAM:
3508 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3509 break;
3510
3511 case STATE_FRAGMENT_PROGRAM:
3512 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3513 break;
3514
3515 case STATE_ENV:
3516 fprintf (stderr, "STATE_ENV ");
3517 break;
3518
3519 case STATE_LOCAL:
3520 fprintf (stderr, "STATE_LOCAL ");
3521 break;
3522
3523 }
3524 fprintf (stderr, "[%d] ", token);
3525}
3526
3527
3528static GLvoid
3529debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3530 struct arb_program *Program)
3531{
3532 struct var_cache *vc;
3533 GLint a, b;
3534
3535 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3536
3537 /* First of all, print out the contents of the var_cache */
3538 vc = vc_head;
3539 while (vc) {
3540 fprintf (stderr, "[%x]\n", vc);
3541 switch (vc->type) {
3542 case vt_none:
3543 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3544 break;
3545 case vt_attrib:
3546 fprintf (stderr, "ATTRIB %s\n", vc->name);
3547 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3548 break;
3549 case vt_param:
3550 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3551 vc->param_binding_begin, vc->param_binding_length);
3552 b = vc->param_binding_begin;
3553 for (a = 0; a < vc->param_binding_length; a++) {
3554 fprintf (stderr, "%s\n",
3555 Program->Parameters->Parameters[a + b].Name);
3556 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3557 print_state_token (Program->Parameters->Parameters[a + b].
3558 StateIndexes[0]);
3559 print_state_token (Program->Parameters->Parameters[a + b].
3560 StateIndexes[1]);
3561 print_state_token (Program->Parameters->Parameters[a + b].
3562 StateIndexes[2]);
3563 print_state_token (Program->Parameters->Parameters[a + b].
3564 StateIndexes[3]);
3565 print_state_token (Program->Parameters->Parameters[a + b].
3566 StateIndexes[4]);
3567 print_state_token (Program->Parameters->Parameters[a + b].
3568 StateIndexes[5]);
3569 }
3570 else
3571 fprintf (stderr, "%f %f %f %f\n",
3572 Program->Parameters->Parameters[a + b].Values[0],
3573 Program->Parameters->Parameters[a + b].Values[1],
3574 Program->Parameters->Parameters[a + b].Values[2],
3575 Program->Parameters->Parameters[a + b].Values[3]);
3576 }
3577 break;
3578 case vt_temp:
3579 fprintf (stderr, "TEMP %s\n", vc->name);
3580 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3581 break;
3582 case vt_output:
3583 fprintf (stderr, "OUTPUT %s\n", vc->name);
3584 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3585 break;
3586 case vt_alias:
3587 fprintf (stderr, "ALIAS %s\n", vc->name);
3588 fprintf (stderr, " binding: 0x%x (%s)\n",
3589 vc->alias_binding, vc->alias_binding->name);
3590 break;
3591 }
3592 vc = vc->next;
3593 }
3594}
3595
Brian Paul72030e02005-11-03 03:30:34 +00003596#endif /* DEBUG_PARSING */
Brian Paul7aebaf32005-10-30 21:23:23 +00003597
3598
3599/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003600 * The main loop for parsing a fragment or vertex program
3601 *
Brian Paul72030e02005-11-03 03:30:34 +00003602 * \return 1 on error, 0 on success
Jouk Jansen40322e12004-04-05 08:50:36 +00003603 */
Brian Paul72030e02005-11-03 03:30:34 +00003604static GLint
Brian Paul45703642005-10-29 15:52:31 +00003605parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3606 struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003607{
Brian Paul72030e02005-11-03 03:30:34 +00003608 const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
3609 ? ctx->Const.FragmentProgram.MaxInstructions
3610 : ctx->Const.VertexProgram.MaxInstructions;
Jouk Jansen40322e12004-04-05 08:50:36 +00003611 GLint err = 0;
3612
Brian Paul72030e02005-11-03 03:30:34 +00003613 ASSERT(MAX_INSTRUCTIONS >= maxInst);
3614
Jouk Jansen40322e12004-04-05 08:50:36 +00003615 Program->MajorVersion = (GLuint) * inst++;
3616 Program->MinorVersion = (GLuint) * inst++;
3617
3618 while (*inst != END) {
3619 switch (*inst++) {
3620
3621 case OPTION:
3622 switch (*inst++) {
3623 case ARB_PRECISION_HINT_FASTEST:
3624 Program->PrecisionOption = GL_FASTEST;
3625 break;
3626
3627 case ARB_PRECISION_HINT_NICEST:
3628 Program->PrecisionOption = GL_NICEST;
3629 break;
3630
3631 case ARB_FOG_EXP:
3632 Program->FogOption = GL_EXP;
3633 break;
3634
3635 case ARB_FOG_EXP2:
3636 Program->FogOption = GL_EXP2;
3637 break;
3638
3639 case ARB_FOG_LINEAR:
3640 Program->FogOption = GL_LINEAR;
3641 break;
3642
3643 case ARB_POSITION_INVARIANT:
3644 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
Brian Paul45cd2f92005-11-03 02:25:10 +00003645 Program->HintPositionInvariant = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003646 break;
3647
3648 case ARB_FRAGMENT_PROGRAM_SHADOW:
3649 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3650 /* TODO ARB_fragment_program_shadow code */
3651 }
3652 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003653
3654 case ARB_DRAW_BUFFERS:
3655 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3656 /* do nothing for now */
3657 }
3658 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003659 }
3660 break;
3661
3662 case INSTRUCTION:
Brian Paul72030e02005-11-03 03:30:34 +00003663 /* check length */
3664 if (Program->Base.NumInstructions + 1 >= maxInst) {
3665 const char *msg = "Max instruction count exceeded";
3666 _mesa_set_program_error(ctx, Program->Position, msg);
3667 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
3668 return 1;
3669 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003670 Program->Position = parse_position (&inst);
Brian Paul72030e02005-11-03 03:30:34 +00003671 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003672 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003673 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003674 &Program->FPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003675 }
3676 else {
Jouk Jansen40322e12004-04-05 08:50:36 +00003677 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003678 &Program->VPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003679 }
3680
Brian Paul72030e02005-11-03 03:30:34 +00003681 /* increment instuction count */
Jouk Jansen40322e12004-04-05 08:50:36 +00003682 Program->Base.NumInstructions++;
3683 break;
3684
3685 case DECLARATION:
3686 err = parse_declaration (ctx, &inst, vc_head, Program);
3687 break;
3688
3689 default:
3690 break;
3691 }
3692
3693 if (err)
3694 break;
3695 }
3696
3697 /* Finally, tag on an OPCODE_END instruction */
3698 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00003699 const GLuint numInst = Program->Base.NumInstructions;
Brian Paul7e807512005-11-05 17:10:45 +00003700 _mesa_init_instruction(Program->FPInstructions + numInst);
3701 Program->FPInstructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003702 /* YYY Wrong Position in program, whatever, at least not random -> crash
3703 Program->Position = parse_position (&inst);
3704 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003705 Program->FPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003706 }
3707 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00003708 const GLuint numInst = Program->Base.NumInstructions;
Brian Paul7e807512005-11-05 17:10:45 +00003709 _mesa_init_instruction(Program->VPInstructions + numInst);
3710 Program->VPInstructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003711 /* YYY Wrong Position in program, whatever, at least not random -> crash
3712 Program->Position = parse_position (&inst);
3713 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003714 Program->VPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003715 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003716 Program->Base.NumInstructions++;
3717
Brian Paul05051032005-11-01 04:36:33 +00003718 /*
3719 * Initialize native counts to logical counts. The device driver may
3720 * change them if program is translated into a hardware program.
3721 */
3722 Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
3723 Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
3724 Program->Base.NumNativeParameters = Program->Base.NumParameters;
3725 Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
3726 Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
3727 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3728 struct fragment_program *fp = (struct fragment_program *) Program;
3729 fp->NumNativeAluInstructions = fp->NumAluInstructions;
3730 fp->NumNativeTexInstructions = fp->NumTexInstructions;
3731 fp->NumNativeTexIndirections = fp->NumTexIndirections;
3732 }
3733
Jouk Jansen40322e12004-04-05 08:50:36 +00003734 return err;
3735}
3736
Brian Paul7aebaf32005-10-30 21:23:23 +00003737
Jouk Jansen40322e12004-04-05 08:50:36 +00003738/* XXX temporary */
Brian Paula6c423d2004-08-25 15:59:48 +00003739__extension__ static char core_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +00003740#include "grammar_syn.h"
3741;
3742
Brian Paul7aebaf32005-10-30 21:23:23 +00003743
Jouk Jansen40322e12004-04-05 08:50:36 +00003744static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3745{
3746 char error_msg[300];
3747 GLint error_pos;
3748
3749 if (grammar_set_reg8 (id, name, value))
3750 return 0;
3751
3752 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3753 _mesa_set_program_error (ctx, error_pos, error_msg);
3754 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3755 return 1;
3756}
3757
3758static int extension_is_supported (const GLubyte *ext)
3759{
Ian Romanick9bdfee32005-07-18 12:31:24 +00003760 const GLubyte *extensions = CALL_GetString(GET_DISPATCH(), (GL_EXTENSIONS));
Jouk Jansen40322e12004-04-05 08:50:36 +00003761 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
Karl Schultz6258b762005-05-05 21:08:07 +00003762 const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
Jouk Jansen40322e12004-04-05 08:50:36 +00003763
3764 while (extensions < end)
3765 {
Brian Paulb3aefd12005-09-19 20:12:32 +00003766 const GLubyte *name_end = (const GLubyte *) _mesa_strstr ((const char *) extensions, " ");
Jouk Jansen40322e12004-04-05 08:50:36 +00003767 if (name_end == NULL)
3768 name_end = end;
3769 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3770 (const char *) extensions, ext_len) == 0)
3771 return 1;
3772 extensions = name_end + 1;
3773 }
3774
3775 return 0;
3776}
3777
3778static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3779{
3780 if (extension_is_supported (extname))
3781 if (set_reg8 (ctx, id, name, 0x01))
3782 return 1;
3783 return 0;
3784}
3785
3786/**
3787 * This kicks everything off.
3788 *
3789 * \param ctx - The GL Context
3790 * \param str - The program string
3791 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003792 * \param program - The arb_program struct to return all the parsed info in
3793 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003794 */
Brian Paul45703642005-10-29 15:52:31 +00003795GLboolean
Jouk Jansen40322e12004-04-05 08:50:36 +00003796_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3797 struct arb_program * program)
3798{
3799 GLint a, err, error_pos;
3800 char error_msg[300];
3801 GLuint parsed_len;
3802 struct var_cache *vc_head;
3803 grammar arbprogram_syn_id;
3804 GLubyte *parsed, *inst;
3805 GLubyte *strz = NULL;
3806 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3807
Brian Paul7f76b8f2004-09-10 01:05:39 +00003808 /* Reset error state */
3809 _mesa_set_program_error(ctx, -1, NULL);
3810
Jouk Jansen40322e12004-04-05 08:50:36 +00003811#if DEBUG_PARSING
3812 fprintf (stderr, "Loading grammar text!\n");
3813#endif
3814
3815 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3816 if (!arbprogram_syn_is_ok) {
3817 grammar grammar_syn_id;
3818 GLint err;
3819 GLuint parsed_len;
3820 byte *parsed;
3821
3822 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3823 if (grammar_syn_id == 0) {
3824 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3825 _mesa_set_program_error (ctx, error_pos, error_msg);
3826 _mesa_error (ctx, GL_INVALID_OPERATION,
3827 "Error loading grammar rule set");
Brian Paul45703642005-10-29 15:52:31 +00003828 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003829 }
3830
3831 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3832
Brian Paul45703642005-10-29 15:52:31 +00003833 /* NOTE: we can't destroy grammar_syn_id right here because
3834 * grammar_destroy() can reset the last error
3835 */
Jouk Jansen40322e12004-04-05 08:50:36 +00003836 if (err == 0) {
3837 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3838 _mesa_set_program_error (ctx, error_pos, error_msg);
3839 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3840
3841 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003842 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003843 }
3844
3845 grammar_destroy (grammar_syn_id);
3846
3847 arbprogram_syn_is_ok = 1;
3848 }
3849
3850 /* create the grammar object */
3851 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3852 if (arbprogram_syn_id == 0) {
3853 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3854 _mesa_set_program_error (ctx, error_pos, error_msg);
3855 _mesa_error (ctx, GL_INVALID_OPERATION,
3856 "Error loading grammer rule set");
Brian Paul45703642005-10-29 15:52:31 +00003857 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003858 }
3859
3860 /* Set program_target register value */
3861 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3862 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3863 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003864 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003865 }
3866
3867 /* Enable all active extensions */
3868 if (enable_ext (ctx, arbprogram_syn_id,
3869 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3870 enable_ext (ctx, arbprogram_syn_id,
3871 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
3872 enable_ext (ctx, arbprogram_syn_id,
3873 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
3874 enable_ext (ctx, arbprogram_syn_id,
3875 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
3876 enable_ext (ctx, arbprogram_syn_id,
3877 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
3878 enable_ext (ctx, arbprogram_syn_id,
3879 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
3880 enable_ext (ctx, arbprogram_syn_id,
3881 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
3882 enable_ext (ctx, arbprogram_syn_id,
Brian Pauledfe0fe2004-08-20 14:21:20 +00003883 (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
3884 enable_ext (ctx, arbprogram_syn_id,
Jouk Jansen40322e12004-04-05 08:50:36 +00003885 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
3886 enable_ext (ctx, arbprogram_syn_id,
3887 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
3888 enable_ext (ctx, arbprogram_syn_id,
Michal Krolad22ce82004-10-11 08:13:25 +00003889 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
3890 enable_ext (ctx, arbprogram_syn_id,
3891 (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003892 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003893 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003894 }
3895
3896 /* check for NULL character occurences */
3897 {
3898 int i;
3899 for (i = 0; i < len; i++)
3900 if (str[i] == '\0') {
3901 _mesa_set_program_error (ctx, i, "invalid character");
3902 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
3903
3904 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003905 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003906 }
3907 }
3908
3909 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003910 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003911 if (!strz) {
3912 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glprogramStringARB");
3913 return GL_FALSE;
3914 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003915 _mesa_memcpy (strz, str, len);
3916 strz[len] = '\0';
3917
3918#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003919 fprintf (stderr, "Checking Grammar!\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00003920#endif
Michal Krolb80bc052004-10-21 14:09:54 +00003921 /* do a fast check on program string - initial production buffer is 4K */
3922 err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00003923
3924 /* Syntax parse error */
3925 if (err == 0) {
3926 _mesa_free (strz);
3927 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3928 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul45703642005-10-29 15:52:31 +00003929 _mesa_error (ctx, GL_INVALID_OPERATION, "glprogramStringARB(syntax error)");
Brian Paul5fe90292004-07-20 21:15:13 +00003930
3931 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00003932#if DEBUG_PARSING
3933 do {
Brian Paul5fe90292004-07-20 21:15:13 +00003934 int line, col;
3935 char *s;
Brian Paul45703642005-10-29 15:52:31 +00003936 fprintf(stderr, "program: %s\n", (char *) strz);
3937 fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
3938 s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos, &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00003939 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
3940 } while (0)
3941#endif
Brian Paul5fe90292004-07-20 21:15:13 +00003942
Jouk Jansen40322e12004-04-05 08:50:36 +00003943 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003944 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003945 }
3946
3947#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003948 fprintf (stderr, "Destroying grammer dict [parse retval: %d]\n", err);
Jouk Jansen40322e12004-04-05 08:50:36 +00003949#endif
3950 grammar_destroy (arbprogram_syn_id);
3951
3952 /* Initialize the arb_program struct */
3953 program->Base.String = strz;
3954 program->Base.NumInstructions =
3955 program->Base.NumTemporaries =
3956 program->Base.NumParameters =
3957 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
3958 program->Parameters = _mesa_new_parameter_list ();
Brian Paul45cd2f92005-11-03 02:25:10 +00003959 program->InputsRead = 0x0;
3960 program->OutputsWritten = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003961 program->Position = 0;
3962 program->MajorVersion = program->MinorVersion = 0;
3963 program->PrecisionOption = GL_DONT_CARE;
3964 program->FogOption = GL_NONE;
3965 program->HintPositionInvariant = GL_FALSE;
3966 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
Brian Paul45cd2f92005-11-03 02:25:10 +00003967 program->TexturesUsed[a] = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003968 program->NumAluInstructions =
3969 program->NumTexInstructions =
3970 program->NumTexIndirections = 0;
3971
Keith Whitwellc3626a92005-11-01 17:25:49 +00003972 program->UsesKill = 0;
3973
Jouk Jansen40322e12004-04-05 08:50:36 +00003974 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00003975 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003976
3977 /* Start examining the tokens in the array */
3978 inst = parsed;
3979
3980 /* Check the grammer rev */
3981 if (*inst++ != REVISION) {
3982 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00003983 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul45cd2f92005-11-03 02:25:10 +00003984 "glProgramStringARB(Grammar version mismatch)");
Brian Paul45703642005-10-29 15:52:31 +00003985 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003986 }
3987 else {
Michal Krolb80bc052004-10-21 14:09:54 +00003988 /* ignore program target */
3989 inst++;
Jouk Jansen40322e12004-04-05 08:50:36 +00003990
3991 err = parse_arb_program (ctx, inst, &vc_head, program);
3992#if DEBUG_PARSING
3993 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
3994#endif
3995 }
3996
3997 /*debug_variables(ctx, vc_head, program); */
3998
3999 /* We're done with the parsed binary array */
4000 var_cache_destroy (&vc_head);
4001
4002 _mesa_free (parsed);
4003#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00004004 fprintf (stderr, "_mesa_parse_arb_program() done\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00004005#endif
Brian Paul45703642005-10-29 15:52:31 +00004006
4007 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00004008}