blob: e33b79ee4c64c7aa2fa0f8bff0582a5fc383b22b [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
Michal Krolb80bc052004-10-21 14:09:54 +00003 * Version: 6.2
Jouk Jansen40322e12004-04-05 08:50:36 +00004 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
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"
40#include "nvvertprog.h"
41#include "nvfragprog.h"
42#include "arbprogparse.h"
43#include "grammar_mesa.h"
44
Alan Hourihane38b317d2004-12-14 09:11:52 +000045#ifndef __extension__
46#if !defined(__GNUC__) || (__GNUC__ < 2) || \
47 ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
Brian Paula6c423d2004-08-25 15:59:48 +000048# define __extension__
49#endif
Alan Hourihane38b317d2004-12-14 09:11:52 +000050#endif
Brian Paula6c423d2004-08-25 15:59:48 +000051
Jouk Jansen40322e12004-04-05 08:50:36 +000052/* TODO:
53 * Fragment Program Stuff:
54 * -----------------------------------------------------
55 *
56 * - things from Michal's email
57 * + overflow on atoi
58 * + not-overflowing floats (don't use parse_integer..)
59 * + can remove range checking in arbparse.c
60 *
61 * - check all limits of number of various variables
62 * + parameters
63 *
64 * - test! test! test!
65 *
66 * Vertex Program Stuff:
67 * -----------------------------------------------------
68 * - Optimize param array usage and count limits correctly, see spec,
69 * section 2.14.3.7
70 * + Record if an array is reference absolutly or relatively (or both)
71 * + For absolute arrays, store a bitmap of accesses
72 * + For single parameters, store an access flag
73 * + After parsing, make a parameter cleanup and merging pass, where
74 * relative arrays are layed out first, followed by abs arrays, and
75 * finally single state.
76 * + Remap offsets for param src and dst registers
77 * + Now we can properly count parameter usage
78 *
79 * - Multiple state binding errors in param arrays (see spec, just before
80 * section 2.14.3.3)
81 * - grep for XXX
82 *
83 * Mesa Stuff
84 * -----------------------------------------------------
85 * - User clipping planes vs. PositionInvariant
86 * - Is it sufficient to just multiply by the mvp to transform in the
87 * PositionInvariant case? Or do we need something more involved?
88 *
89 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
90 * - fetch state listed in program_parameters list
91 * + WTF should this go???
92 * + currently in nvvertexec.c and s_nvfragprog.c
93 *
94 * - allow for multiple address registers (and fetch address regs properly)
95 *
96 * Cosmetic Stuff
97 * -----------------------------------------------------
98 * - remove any leftover unused grammer.c stuff (dict_ ?)
99 * - fix grammer.c error handling so its not static
100 * - #ifdef around stuff pertaining to extentions
101 *
102 * Outstanding Questions:
103 * -----------------------------------------------------
104 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
105 * what gets hacked off because of this:
106 * + VERTEX_ATTRIB_MATRIXINDEX
107 * + VERTEX_ATTRIB_WEIGHT
108 * + MATRIX_MODELVIEW
109 * + MATRIX_PALETTE
110 *
111 * - When can we fetch env/local params from their own register files, and
112 * when to we have to fetch them into the main state register file?
113 * (think arrays)
114 *
115 * Grammar Changes:
116 * -----------------------------------------------------
117 */
118
119/* Changes since moving the file to shader directory
120
1212004-III-4 ------------------------------------------------------------
122- added #include "grammar_mesa.h"
123- removed grammar specific code part (it resides now in grammar.c)
124- added GL_ARB_fragment_program_shadow tokens
125- modified #include "arbparse_syn.h"
126- major changes inside _mesa_parse_arb_program()
127- check the program string for '\0' characters
128- copy the program string to a one-byte-longer location to have
129 it null-terminated
130- position invariance test (not writing to result.position) moved
131 to syntax part
132*/
133
134typedef GLubyte *production;
135
136/**
137 * This is the text describing the rules to parse the grammar
138 */
Brian Paula6c423d2004-08-25 15:59:48 +0000139__extension__ static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000140#include "arbprogram_syn.h"
141;
142
143/**
144 * These should match up with the values defined in arbprogram.syn
145 */
146
147/*
148 Changes:
149 - changed and merged V_* and F_* opcode values to OP_*.
150 - added GL_ARB_fragment_program_shadow specific tokens (michal)
151*/
Michal Krolb80bc052004-10-21 14:09:54 +0000152#define REVISION 0x09
Jouk Jansen40322e12004-04-05 08:50:36 +0000153
154/* program type */
155#define FRAGMENT_PROGRAM 0x01
156#define VERTEX_PROGRAM 0x02
157
158/* program section */
159#define OPTION 0x01
160#define INSTRUCTION 0x02
161#define DECLARATION 0x03
162#define END 0x04
163
Michal Krolb80bc052004-10-21 14:09:54 +0000164/* GL_ARB_fragment_program option */
165#define ARB_PRECISION_HINT_FASTEST 0x00
166#define ARB_PRECISION_HINT_NICEST 0x01
167#define ARB_FOG_EXP 0x02
168#define ARB_FOG_EXP2 0x03
169#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000170
Michal Krolb80bc052004-10-21 14:09:54 +0000171/* GL_ARB_vertex_program option */
172#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000173
Michal Krolb80bc052004-10-21 14:09:54 +0000174/* GL_ARB_fragment_program_shadow option */
175#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000176
Michal Krolb80bc052004-10-21 14:09:54 +0000177/* GL_ARB_draw_buffers option */
178#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000179
Jouk Jansen40322e12004-04-05 08:50:36 +0000180/* GL_ARB_fragment_program instruction class */
181#define OP_ALU_INST 0x00
182#define OP_TEX_INST 0x01
183
184/* GL_ARB_vertex_program instruction class */
185/* OP_ALU_INST */
186
187/* GL_ARB_fragment_program instruction type */
188#define OP_ALU_VECTOR 0x00
189#define OP_ALU_SCALAR 0x01
190#define OP_ALU_BINSC 0x02
191#define OP_ALU_BIN 0x03
192#define OP_ALU_TRI 0x04
193#define OP_ALU_SWZ 0x05
194#define OP_TEX_SAMPLE 0x06
195#define OP_TEX_KIL 0x07
196
197/* GL_ARB_vertex_program instruction type */
198#define OP_ALU_ARL 0x08
199/* OP_ALU_VECTOR */
200/* OP_ALU_SCALAR */
201/* OP_ALU_BINSC */
202/* OP_ALU_BIN */
203/* OP_ALU_TRI */
204/* OP_ALU_SWZ */
205
206/* GL_ARB_fragment_program instruction code */
207#define OP_ABS 0x00
208#define OP_ABS_SAT 0x1B
209#define OP_FLR 0x09
210#define OP_FLR_SAT 0x26
211#define OP_FRC 0x0A
212#define OP_FRC_SAT 0x27
213#define OP_LIT 0x0C
214#define OP_LIT_SAT 0x2A
215#define OP_MOV 0x11
216#define OP_MOV_SAT 0x30
217#define OP_COS 0x1F
218#define OP_COS_SAT 0x20
219#define OP_EX2 0x07
220#define OP_EX2_SAT 0x25
221#define OP_LG2 0x0B
222#define OP_LG2_SAT 0x29
223#define OP_RCP 0x14
224#define OP_RCP_SAT 0x33
225#define OP_RSQ 0x15
226#define OP_RSQ_SAT 0x34
227#define OP_SIN 0x38
228#define OP_SIN_SAT 0x39
229#define OP_SCS 0x35
230#define OP_SCS_SAT 0x36
231#define OP_POW 0x13
232#define OP_POW_SAT 0x32
233#define OP_ADD 0x01
234#define OP_ADD_SAT 0x1C
235#define OP_DP3 0x03
236#define OP_DP3_SAT 0x21
237#define OP_DP4 0x04
238#define OP_DP4_SAT 0x22
239#define OP_DPH 0x05
240#define OP_DPH_SAT 0x23
241#define OP_DST 0x06
242#define OP_DST_SAT 0x24
243#define OP_MAX 0x0F
244#define OP_MAX_SAT 0x2E
245#define OP_MIN 0x10
246#define OP_MIN_SAT 0x2F
247#define OP_MUL 0x12
248#define OP_MUL_SAT 0x31
249#define OP_SGE 0x16
250#define OP_SGE_SAT 0x37
251#define OP_SLT 0x17
252#define OP_SLT_SAT 0x3A
253#define OP_SUB 0x18
254#define OP_SUB_SAT 0x3B
255#define OP_XPD 0x1A
256#define OP_XPD_SAT 0x43
257#define OP_CMP 0x1D
258#define OP_CMP_SAT 0x1E
259#define OP_LRP 0x2B
260#define OP_LRP_SAT 0x2C
261#define OP_MAD 0x0E
262#define OP_MAD_SAT 0x2D
263#define OP_SWZ 0x19
264#define OP_SWZ_SAT 0x3C
265#define OP_TEX 0x3D
266#define OP_TEX_SAT 0x3E
267#define OP_TXB 0x3F
268#define OP_TXB_SAT 0x40
269#define OP_TXP 0x41
270#define OP_TXP_SAT 0x42
271#define OP_KIL 0x28
272
273/* GL_ARB_vertex_program instruction code */
274#define OP_ARL 0x02
275/* OP_ABS */
276/* OP_FLR */
277/* OP_FRC */
278/* OP_LIT */
279/* OP_MOV */
280/* OP_EX2 */
281#define OP_EXP 0x08
282/* OP_LG2 */
283#define OP_LOG 0x0D
284/* OP_RCP */
285/* OP_RSQ */
286/* OP_POW */
287/* OP_ADD */
288/* OP_DP3 */
289/* OP_DP4 */
290/* OP_DPH */
291/* OP_DST */
292/* OP_MAX */
293/* OP_MIN */
294/* OP_MUL */
295/* OP_SGE */
296/* OP_SLT */
297/* OP_SUB */
298/* OP_XPD */
299/* OP_MAD */
300/* OP_SWZ */
301
302/* fragment attribute binding */
303#define FRAGMENT_ATTRIB_COLOR 0x01
304#define FRAGMENT_ATTRIB_TEXCOORD 0x02
305#define FRAGMENT_ATTRIB_FOGCOORD 0x03
306#define FRAGMENT_ATTRIB_POSITION 0x04
307
308/* vertex attribute binding */
309#define VERTEX_ATTRIB_POSITION 0x01
310#define VERTEX_ATTRIB_WEIGHT 0x02
311#define VERTEX_ATTRIB_NORMAL 0x03
312#define VERTEX_ATTRIB_COLOR 0x04
313#define VERTEX_ATTRIB_FOGCOORD 0x05
314#define VERTEX_ATTRIB_TEXCOORD 0x06
315#define VERTEX_ATTRIB_MATRIXINDEX 0x07
316#define VERTEX_ATTRIB_GENERIC 0x08
317
318/* fragment result binding */
319#define FRAGMENT_RESULT_COLOR 0x01
320#define FRAGMENT_RESULT_DEPTH 0x02
321
322/* vertex result binding */
323#define VERTEX_RESULT_POSITION 0x01
324#define VERTEX_RESULT_COLOR 0x02
325#define VERTEX_RESULT_FOGCOORD 0x03
326#define VERTEX_RESULT_POINTSIZE 0x04
327#define VERTEX_RESULT_TEXCOORD 0x05
328
329/* texture target */
330#define TEXTARGET_1D 0x01
331#define TEXTARGET_2D 0x02
332#define TEXTARGET_3D 0x03
333#define TEXTARGET_RECT 0x04
334#define TEXTARGET_CUBE 0x05
335/* GL_ARB_fragment_program_shadow */
336#define TEXTARGET_SHADOW1D 0x06
337#define TEXTARGET_SHADOW2D 0x07
338#define TEXTARGET_SHADOWRECT 0x08
339
340/* face type */
341#define FACE_FRONT 0x00
342#define FACE_BACK 0x01
343
344/* color type */
345#define COLOR_PRIMARY 0x00
346#define COLOR_SECONDARY 0x01
347
348/* component */
349#define COMPONENT_X 0x00
350#define COMPONENT_Y 0x01
351#define COMPONENT_Z 0x02
352#define COMPONENT_W 0x03
353#define COMPONENT_0 0x04
354#define COMPONENT_1 0x05
355
356/* array index type */
357#define ARRAY_INDEX_ABSOLUTE 0x00
358#define ARRAY_INDEX_RELATIVE 0x01
359
360/* matrix name */
361#define MATRIX_MODELVIEW 0x01
362#define MATRIX_PROJECTION 0x02
363#define MATRIX_MVP 0x03
364#define MATRIX_TEXTURE 0x04
365#define MATRIX_PALETTE 0x05
366#define MATRIX_PROGRAM 0x06
367
368/* matrix modifier */
369#define MATRIX_MODIFIER_IDENTITY 0x00
370#define MATRIX_MODIFIER_INVERSE 0x01
371#define MATRIX_MODIFIER_TRANSPOSE 0x02
372#define MATRIX_MODIFIER_INVTRANS 0x03
373
374/* constant type */
375#define CONSTANT_SCALAR 0x01
376#define CONSTANT_VECTOR 0x02
377
378/* program param type */
379#define PROGRAM_PARAM_ENV 0x01
380#define PROGRAM_PARAM_LOCAL 0x02
381
382/* register type */
383#define REGISTER_ATTRIB 0x01
384#define REGISTER_PARAM 0x02
385#define REGISTER_RESULT 0x03
386#define REGISTER_ESTABLISHED_NAME 0x04
387
388/* param binding */
389#define PARAM_NULL 0x00
390#define PARAM_ARRAY_ELEMENT 0x01
391#define PARAM_STATE_ELEMENT 0x02
392#define PARAM_PROGRAM_ELEMENT 0x03
393#define PARAM_PROGRAM_ELEMENTS 0x04
394#define PARAM_CONSTANT 0x05
395
396/* param state property */
397#define STATE_MATERIAL_PARSER 0x01
398#define STATE_LIGHT_PARSER 0x02
399#define STATE_LIGHT_MODEL 0x03
400#define STATE_LIGHT_PROD 0x04
401#define STATE_FOG 0x05
402#define STATE_MATRIX_ROWS 0x06
403/* GL_ARB_fragment_program */
404#define STATE_TEX_ENV 0x07
405#define STATE_DEPTH 0x08
406/* GL_ARB_vertex_program */
407#define STATE_TEX_GEN 0x09
408#define STATE_CLIP_PLANE 0x0A
409#define STATE_POINT 0x0B
410
411/* state material property */
412#define MATERIAL_AMBIENT 0x01
413#define MATERIAL_DIFFUSE 0x02
414#define MATERIAL_SPECULAR 0x03
415#define MATERIAL_EMISSION 0x04
416#define MATERIAL_SHININESS 0x05
417
418/* state light property */
419#define LIGHT_AMBIENT 0x01
420#define LIGHT_DIFFUSE 0x02
421#define LIGHT_SPECULAR 0x03
422#define LIGHT_POSITION 0x04
423#define LIGHT_ATTENUATION 0x05
424#define LIGHT_HALF 0x06
425#define LIGHT_SPOT_DIRECTION 0x07
426
427/* state light model property */
428#define LIGHT_MODEL_AMBIENT 0x01
429#define LIGHT_MODEL_SCENECOLOR 0x02
430
431/* state light product property */
432#define LIGHT_PROD_AMBIENT 0x01
433#define LIGHT_PROD_DIFFUSE 0x02
434#define LIGHT_PROD_SPECULAR 0x03
435
436/* state texture environment property */
437#define TEX_ENV_COLOR 0x01
438
439/* state texture generation coord property */
440#define TEX_GEN_EYE 0x01
441#define TEX_GEN_OBJECT 0x02
442
443/* state fog property */
444#define FOG_COLOR 0x01
445#define FOG_PARAMS 0x02
446
447/* state depth property */
448#define DEPTH_RANGE 0x01
449
450/* state point parameters property */
451#define POINT_SIZE 0x01
452#define POINT_ATTENUATION 0x02
453
454/* declaration */
455#define ATTRIB 0x01
456#define PARAM 0x02
457#define TEMP 0x03
458#define OUTPUT 0x04
459#define ALIAS 0x05
460/* GL_ARB_vertex_program */
461#define ADDRESS 0x06
462
463/*-----------------------------------------------------------------------
464 * From here on down is the semantic checking portion
465 *
466 */
467
468/**
469 * Variable Table Handling functions
470 */
471typedef enum
472{
473 vt_none,
474 vt_address,
475 vt_attrib,
476 vt_param,
477 vt_temp,
478 vt_output,
479 vt_alias
480} var_type;
481
482
483/*
484 * Setting an explicit field for each of the binding properties is a bit wasteful
485 * of space, but it should be much more clear when reading later on..
486 */
487struct var_cache
488{
489 GLubyte *name;
490 var_type type;
491 GLuint address_binding; /* The index of the address register we should
492 * be using */
493 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
494 GLuint attrib_binding_idx; /* The index into the attrib register file corresponding
495 * to the state in attrib_binding */
496 GLuint attrib_is_generic; /* If the attrib was specified through a generic
497 * vertex attrib */
498 GLuint temp_binding; /* The index of the temp register we are to use */
499 GLuint output_binding; /* For type vt_output, see nvfragprog.h for values */
500 GLuint output_binding_idx; /* This is the index into the result register file
501 * corresponding to the bound result state */
502 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
503 * that this is aliased to */
504 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
505 * PROGRAM_ENV_PARAM} */
506 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
507 * the tokens representing our bound state (or constants)
508 * start */
509 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
510 * we take up with our state tokens or constants. Note that
511 * this is _not_ the same as the number of param registers
512 * we eventually use */
513 struct var_cache *next;
514};
515
516static GLvoid
517var_cache_create (struct var_cache **va)
518{
519 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
520 if (*va) {
521 (**va).name = NULL;
522 (**va).type = vt_none;
523 (**va).attrib_binding = ~0;
524 (**va).attrib_is_generic = 0;
525 (**va).temp_binding = ~0;
526 (**va).output_binding = ~0;
527 (**va).output_binding_idx = ~0;
528 (**va).param_binding_type = ~0;
529 (**va).param_binding_begin = ~0;
530 (**va).param_binding_length = ~0;
531 (**va).alias_binding = NULL;
532 (**va).next = NULL;
533 }
534}
535
536static GLvoid
537var_cache_destroy (struct var_cache **va)
538{
539 if (*va) {
540 var_cache_destroy (&(**va).next);
541 _mesa_free (*va);
542 *va = NULL;
543 }
544}
545
546static GLvoid
547var_cache_append (struct var_cache **va, struct var_cache *nv)
548{
549 if (*va)
550 var_cache_append (&(**va).next, nv);
551 else
552 *va = nv;
553}
554
555static struct var_cache *
556var_cache_find (struct var_cache *va, GLubyte * name)
557{
Brian Paul0a360cf2005-01-17 01:21:03 +0000558 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000559
560 while (va) {
561 if (!strcmp ( (const char*) name, (const char*) va->name)) {
562 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000563 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000564 return va;
565 }
566
567 va = va->next;
568 }
569
570 return NULL;
571}
572
573/**
574 * constructs an integer from 4 GLubytes in LE format
575 */
576static GLuint
577parse_position (GLubyte ** inst)
578{
579 GLuint value;
580
581 value = (GLuint) (*(*inst)++);
582 value += (GLuint) (*(*inst)++) * 0x100;
583 value += (GLuint) (*(*inst)++) * 0x10000;
584 value += (GLuint) (*(*inst)++) * 0x1000000;
585
586 return value;
587}
588
589/**
590 * This will, given a string, lookup the string as a variable name in the
591 * var cache. If the name is found, the var cache node corresponding to the
592 * var name is returned. If it is not found, a new entry is allocated
593 *
594 * \param I Points into the binary array where the string identifier begins
595 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
596 * \return The location on the var_cache corresponding the the string starting at I
597 */
598static struct var_cache *
599parse_string (GLubyte ** inst, struct var_cache **vc_head,
600 struct arb_program *Program, GLuint * found)
601{
602 GLubyte *i = *inst;
603 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000604 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000605
606 *inst += _mesa_strlen ((char *) i) + 1;
607
608 va = var_cache_find (*vc_head, i);
609
610 if (va) {
611 *found = 1;
612 return va;
613 }
614
615 *found = 0;
616 var_cache_create (&va);
617 va->name = i;
618
619 var_cache_append (vc_head, va);
620
621 return va;
622}
623
624static char *
625parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
626{
627 GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000628 (void) Program;
629
Jouk Jansen40322e12004-04-05 08:50:36 +0000630 *inst += _mesa_strlen ((char *) i) + 1;
631
632 return (char *) i;
633}
634
635/**
Brian Paul05908952004-06-08 15:20:23 +0000636 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000637 */
Brian Paul05908952004-06-08 15:20:23 +0000638static GLint
Jouk Jansen40322e12004-04-05 08:50:36 +0000639parse_sign (GLubyte ** inst)
640{
641 /*return *(*inst)++ != '+'; */
642
643 if (**inst == '-') {
644 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000645 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000646 }
647 else if (**inst == '+') {
648 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000649 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000650 }
651
Brian Paul05908952004-06-08 15:20:23 +0000652 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000653}
654
655/**
656 * parses and returns signed integer
657 */
658static GLint
659parse_integer (GLubyte ** inst, struct arb_program *Program)
660{
661 GLint sign;
662 GLint value;
663
664 /* check if *inst points to '+' or '-'
665 * if yes, grab the sign and increment *inst
666 */
667 sign = parse_sign (inst);
668
669 /* now check if *inst points to 0
670 * if yes, increment the *inst and return the default value
671 */
672 if (**inst == 0) {
673 (*inst)++;
674 return 0;
675 }
676
677 /* parse the integer as you normally would do it */
678 value = _mesa_atoi (parse_string_without_adding (inst, Program));
679
680 /* now, after terminating 0 there is a position
681 * to parse it - parse_position()
682 */
683 Program->Position = parse_position (inst);
684
Brian Paul05908952004-06-08 15:20:23 +0000685 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000686}
687
688/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000689 Accumulate this string of digits, and return them as
690 a large integer represented in floating point (for range).
691 If scale is not NULL, also accumulates a power-of-ten
692 integer scale factor that represents the number of digits
693 in the string.
694*/
695static GLdouble
696parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
697{
698 GLdouble value = 0.0;
699 GLdouble oscale = 1.0;
700
701 if (**inst == 0) { /* this string of digits is empty-- do nothing */
702 (*inst)++;
703 }
704 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000705 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000706 GLubyte digit = *((*inst)++);
707 value = value * 10.0 + (GLint) (digit - '0');
708 oscale *= 10.0;
709 }
710 assert(**inst == 0); /* integer string should end with 0 */
711 (*inst)++; /* skip over terminating 0 */
712 Program->Position = parse_position(inst); /* skip position (from integer) */
713 }
714 if (scale)
715 *scale = oscale;
716 return value;
717}
718
719/**
720 Parse an unsigned floating-point number from this stream of tokenized
721 characters. Example floating-point formats supported:
722 12.34
723 12
724 0.34
725 .34
726 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000727 */
728static GLfloat
729parse_float (GLubyte ** inst, struct arb_program *Program)
730{
Brian Paul1ff8f502005-02-16 15:08:29 +0000731 GLint exponent;
732 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000733
Brian Paul1ff8f502005-02-16 15:08:29 +0000734 whole = parse_float_string(inst, Program, 0);
735 fraction = parse_float_string(inst, Program, &fracScale);
736
737 /* Parse signed exponent */
738 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000739
Brian Paul1ff8f502005-02-16 15:08:29 +0000740 /* Assemble parts of floating-point number: */
741 return (GLfloat) ((whole + fraction / fracScale) *
742 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000743}
744
745
746/**
747 */
748static GLfloat
749parse_signed_float (GLubyte ** inst, struct arb_program *Program)
750{
Brian Paul05908952004-06-08 15:20:23 +0000751 GLint sign = parse_sign (inst);
752 GLfloat value = parse_float (inst, Program);
753 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000754}
755
756/**
757 * This picks out a constant value from the parsed array. The constant vector is r
758 * returned in the *values array, which should be of length 4.
759 *
760 * \param values - The 4 component vector with the constant value in it
761 */
762static GLvoid
763parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
764 GLboolean use)
765{
766 GLuint components, i;
767
768
769 switch (*(*inst)++) {
770 case CONSTANT_SCALAR:
771 if (use == GL_TRUE) {
772 values[0] =
773 values[1] =
774 values[2] = values[3] = parse_float (inst, Program);
775 }
776 else {
777 values[0] =
778 values[1] =
779 values[2] = values[3] = parse_signed_float (inst, Program);
780 }
781
782 break;
783 case CONSTANT_VECTOR:
784 values[0] = values[1] = values[2] = 0;
785 values[3] = 1;
786 components = *(*inst)++;
787 for (i = 0; i < components; i++) {
788 values[i] = parse_signed_float (inst, Program);
789 }
790 break;
791 }
792}
793
794/**
795 * \param offset The offset from the address register that we should
796 * address
797 *
798 * \return 0 on sucess, 1 on error
799 */
800static GLuint
801parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
802 GLint *offset)
803{
804 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000805 return 0;
806}
807
808/**
809 * \param color 0 if color type is primary, 1 if color type is secondary
810 * \return 0 on sucess, 1 on error
811 */
812static GLuint
813parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
814 GLint * color)
815{
Brian Paula6c423d2004-08-25 15:59:48 +0000816 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000817 *color = *(*inst)++ != COLOR_PRIMARY;
818 return 0;
819}
820
821/**
822 * Get an integer corresponding to a generic vertex attribute.
823 *
824 * \return 0 on sucess, 1 on error
825 */
826static GLuint
827parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
828 struct arb_program *Program, GLuint *attrib)
829{
Brian Paulbd997cd2004-07-20 21:12:56 +0000830 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000831
Brian Paulbd997cd2004-07-20 21:12:56 +0000832 if ((i < 0) || (i > MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000833 {
834 _mesa_set_program_error (ctx, Program->Position,
835 "Invalid generic vertex attribute index");
836 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
837
838 return 1;
839 }
840
Brian Paulbd997cd2004-07-20 21:12:56 +0000841 *attrib = (GLuint) i;
842
Jouk Jansen40322e12004-04-05 08:50:36 +0000843 return 0;
844}
845
846
847/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000848 * \param color The index of the color buffer to write into
849 * \return 0 on sucess, 1 on error
850 */
851static GLuint
852parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
853 struct arb_program *Program, GLuint * color)
854{
855 GLint i = parse_integer (inst, Program);
856
857 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
858 _mesa_set_program_error (ctx, Program->Position,
859 "Invalid draw buffer index");
860 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid draw buffer index");
861 return 1;
862 }
863
864 *color = (GLuint) i;
865 return 0;
866}
867
868
869/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000870 * \param coord The texture unit index
871 * \return 0 on sucess, 1 on error
872 */
873static GLuint
874parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
875 struct arb_program *Program, GLuint * coord)
876{
Brian Paulbd997cd2004-07-20 21:12:56 +0000877 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000878
Brian Paula6c423d2004-08-25 15:59:48 +0000879 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000880 _mesa_set_program_error (ctx, Program->Position,
881 "Invalid texture unit index");
882 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
883 return 1;
884 }
885
Brian Paulbd997cd2004-07-20 21:12:56 +0000886 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000887 return 0;
888}
889
890/**
891 * \param coord The weight index
892 * \return 0 on sucess, 1 on error
893 */
894static GLuint
895parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
896 GLint * coord)
897{
898 *coord = parse_integer (inst, Program);
899
900 if ((*coord < 0) || (*coord >= 1)) {
901 _mesa_set_program_error (ctx, Program->Position,
902 "Invalid weight index");
903 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
904 return 1;
905 }
906
907 return 0;
908}
909
910/**
911 * \param coord The clip plane index
912 * \return 0 on sucess, 1 on error
913 */
914static GLuint
915parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
916 struct arb_program *Program, GLint * coord)
917{
918 *coord = parse_integer (inst, Program);
919
920 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
921 _mesa_set_program_error (ctx, Program->Position,
922 "Invalid clip plane index");
923 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
924 return 1;
925 }
926
927 return 0;
928}
929
930
931/**
932 * \return 0 on front face, 1 on back face
933 */
934static GLuint
935parse_face_type (GLubyte ** inst)
936{
937 switch (*(*inst)++) {
938 case FACE_FRONT:
939 return 0;
940
941 case FACE_BACK:
942 return 1;
943 }
944 return 0;
945}
946
947
948/**
949 * Given a matrix and a modifier token on the binary array, return tokens
950 * that _mesa_fetch_state() [program.c] can understand.
951 *
952 * \param matrix - the matrix we are talking about
953 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
954 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
955 * \return 0 on sucess, 1 on failure
956 */
957static GLuint
958parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
959 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
960{
961 GLubyte mat = *(*inst)++;
962
963 *matrix_idx = 0;
964
965 switch (mat) {
966 case MATRIX_MODELVIEW:
967 *matrix = STATE_MODELVIEW;
968 *matrix_idx = parse_integer (inst, Program);
969 if (*matrix_idx > 0) {
970 _mesa_set_program_error (ctx, Program->Position,
971 "ARB_vertex_blend not supported\n");
972 _mesa_error (ctx, GL_INVALID_OPERATION,
973 "ARB_vertex_blend not supported\n");
974 return 1;
975 }
976 break;
977
978 case MATRIX_PROJECTION:
979 *matrix = STATE_PROJECTION;
980 break;
981
982 case MATRIX_MVP:
983 *matrix = STATE_MVP;
984 break;
985
986 case MATRIX_TEXTURE:
987 *matrix = STATE_TEXTURE;
988 *matrix_idx = parse_integer (inst, Program);
989 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
990 _mesa_set_program_error (ctx, Program->Position,
991 "Invalid Texture Unit");
992 _mesa_error (ctx, GL_INVALID_OPERATION,
993 "Invalid Texture Unit: %d", *matrix_idx);
994 return 1;
995 }
996 break;
997
998 /* This is not currently supported (ARB_matrix_palette) */
999 case MATRIX_PALETTE:
1000 *matrix_idx = parse_integer (inst, Program);
1001 _mesa_set_program_error (ctx, Program->Position,
1002 "ARB_matrix_palette not supported\n");
1003 _mesa_error (ctx, GL_INVALID_OPERATION,
1004 "ARB_matrix_palette not supported\n");
1005 return 1;
1006 break;
1007
1008 case MATRIX_PROGRAM:
1009 *matrix = STATE_PROGRAM;
1010 *matrix_idx = parse_integer (inst, Program);
1011 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
1012 _mesa_set_program_error (ctx, Program->Position,
1013 "Invalid Program Matrix");
1014 _mesa_error (ctx, GL_INVALID_OPERATION,
1015 "Invalid Program Matrix: %d", *matrix_idx);
1016 return 1;
1017 }
1018 break;
1019 }
1020
1021 switch (*(*inst)++) {
1022 case MATRIX_MODIFIER_IDENTITY:
1023 *matrix_modifier = 0;
1024 break;
1025 case MATRIX_MODIFIER_INVERSE:
1026 *matrix_modifier = STATE_MATRIX_INVERSE;
1027 break;
1028 case MATRIX_MODIFIER_TRANSPOSE:
1029 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1030 break;
1031 case MATRIX_MODIFIER_INVTRANS:
1032 *matrix_modifier = STATE_MATRIX_INVTRANS;
1033 break;
1034 }
1035
1036 return 0;
1037}
1038
1039
1040/**
1041 * This parses a state string (rather, the binary version of it) into
1042 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1043 *
1044 * \param inst - the start in the binary arry to start working from
1045 * \param state_tokens - the storage for the 6-token state description
1046 * \return - 0 on sucess, 1 on error
1047 */
1048static GLuint
1049parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
1050 struct arb_program *Program, GLint * state_tokens)
1051{
1052 switch (*(*inst)++) {
1053 case STATE_MATERIAL_PARSER:
1054 state_tokens[0] = STATE_MATERIAL;
1055 state_tokens[1] = parse_face_type (inst);
1056 switch (*(*inst)++) {
1057 case MATERIAL_AMBIENT:
1058 state_tokens[2] = STATE_AMBIENT;
1059 break;
1060 case MATERIAL_DIFFUSE:
1061 state_tokens[2] = STATE_DIFFUSE;
1062 break;
1063 case MATERIAL_SPECULAR:
1064 state_tokens[2] = STATE_SPECULAR;
1065 break;
1066 case MATERIAL_EMISSION:
1067 state_tokens[2] = STATE_EMISSION;
1068 break;
1069 case MATERIAL_SHININESS:
1070 state_tokens[2] = STATE_SHININESS;
1071 break;
1072 }
1073 break;
1074
1075 case STATE_LIGHT_PARSER:
1076 state_tokens[0] = STATE_LIGHT;
1077 state_tokens[1] = parse_integer (inst, Program);
1078
1079 /* Check the value of state_tokens[1] against the # of lights */
1080 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1081 _mesa_set_program_error (ctx, Program->Position,
1082 "Invalid Light Number");
1083 _mesa_error (ctx, GL_INVALID_OPERATION,
1084 "Invalid Light Number: %d", state_tokens[1]);
1085 return 1;
1086 }
1087
1088 switch (*(*inst)++) {
1089 case LIGHT_AMBIENT:
1090 state_tokens[2] = STATE_AMBIENT;
1091 break;
1092 case LIGHT_DIFFUSE:
1093 state_tokens[2] = STATE_DIFFUSE;
1094 break;
1095 case LIGHT_SPECULAR:
1096 state_tokens[2] = STATE_SPECULAR;
1097 break;
1098 case LIGHT_POSITION:
1099 state_tokens[2] = STATE_POSITION;
1100 break;
1101 case LIGHT_ATTENUATION:
1102 state_tokens[2] = STATE_ATTENUATION;
1103 break;
1104 case LIGHT_HALF:
1105 state_tokens[2] = STATE_HALF;
1106 break;
1107 case LIGHT_SPOT_DIRECTION:
1108 state_tokens[2] = STATE_SPOT_DIRECTION;
1109 break;
1110 }
1111 break;
1112
1113 case STATE_LIGHT_MODEL:
1114 switch (*(*inst)++) {
1115 case LIGHT_MODEL_AMBIENT:
1116 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1117 break;
1118 case LIGHT_MODEL_SCENECOLOR:
1119 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1120 state_tokens[1] = parse_face_type (inst);
1121 break;
1122 }
1123 break;
1124
1125 case STATE_LIGHT_PROD:
1126 state_tokens[0] = STATE_LIGHTPROD;
1127 state_tokens[1] = parse_integer (inst, Program);
1128
1129 /* Check the value of state_tokens[1] against the # of lights */
1130 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1131 _mesa_set_program_error (ctx, Program->Position,
1132 "Invalid Light Number");
1133 _mesa_error (ctx, GL_INVALID_OPERATION,
1134 "Invalid Light Number: %d", state_tokens[1]);
1135 return 1;
1136 }
1137
1138 state_tokens[2] = parse_face_type (inst);
1139 switch (*(*inst)++) {
1140 case LIGHT_PROD_AMBIENT:
1141 state_tokens[3] = STATE_AMBIENT;
1142 break;
1143 case LIGHT_PROD_DIFFUSE:
1144 state_tokens[3] = STATE_DIFFUSE;
1145 break;
1146 case LIGHT_PROD_SPECULAR:
1147 state_tokens[3] = STATE_SPECULAR;
1148 break;
1149 }
1150 break;
1151
1152
1153 case STATE_FOG:
1154 switch (*(*inst)++) {
1155 case FOG_COLOR:
1156 state_tokens[0] = STATE_FOG_COLOR;
1157 break;
1158 case FOG_PARAMS:
1159 state_tokens[0] = STATE_FOG_PARAMS;
1160 break;
1161 }
1162 break;
1163
1164 case STATE_TEX_ENV:
1165 state_tokens[1] = parse_integer (inst, Program);
1166 switch (*(*inst)++) {
1167 case TEX_ENV_COLOR:
1168 state_tokens[0] = STATE_TEXENV_COLOR;
1169 break;
1170 }
1171 break;
1172
1173 case STATE_TEX_GEN:
1174 {
1175 GLuint type, coord;
1176
1177 state_tokens[0] = STATE_TEXGEN;
1178 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1179
1180 if (parse_texcoord_num (ctx, inst, Program, &coord))
1181 return 1;
1182 state_tokens[1] = coord;
1183
1184 /* EYE or OBJECT */
1185 type = *(*inst++);
1186
1187 /* 0 - s, 1 - t, 2 - r, 3 - q */
1188 coord = *(*inst++);
1189
1190 if (type == TEX_GEN_EYE) {
1191 switch (coord) {
1192 case COMPONENT_X:
1193 state_tokens[2] = STATE_TEXGEN_EYE_S;
1194 break;
1195 case COMPONENT_Y:
1196 state_tokens[2] = STATE_TEXGEN_EYE_T;
1197 break;
1198 case COMPONENT_Z:
1199 state_tokens[2] = STATE_TEXGEN_EYE_R;
1200 break;
1201 case COMPONENT_W:
1202 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1203 break;
1204 }
1205 }
1206 else {
1207 switch (coord) {
1208 case COMPONENT_X:
1209 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1210 break;
1211 case COMPONENT_Y:
1212 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1213 break;
1214 case COMPONENT_Z:
1215 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1216 break;
1217 case COMPONENT_W:
1218 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1219 break;
1220 }
1221 }
1222 }
1223 break;
1224
1225 case STATE_DEPTH:
1226 switch (*(*inst)++) {
1227 case DEPTH_RANGE:
1228 state_tokens[0] = STATE_DEPTH_RANGE;
1229 break;
1230 }
1231 break;
1232
1233 case STATE_CLIP_PLANE:
1234 state_tokens[0] = STATE_CLIPPLANE;
1235 state_tokens[1] = parse_integer (inst, Program);
1236 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
1237 return 1;
1238 break;
1239
1240 case STATE_POINT:
1241 switch (*(*inst++)) {
1242 case POINT_SIZE:
1243 state_tokens[0] = STATE_POINT_SIZE;
1244 break;
1245
1246 case POINT_ATTENUATION:
1247 state_tokens[0] = STATE_POINT_ATTENUATION;
1248 break;
1249 }
1250 break;
1251
1252 /* XXX: I think this is the correct format for a matrix row */
1253 case STATE_MATRIX_ROWS:
1254 state_tokens[0] = STATE_MATRIX;
1255 if (parse_matrix
1256 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
1257 &state_tokens[5]))
1258 return 1;
1259
1260 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
1261
1262 if ((**inst) != 0) { /* Either the last row, 0 */
1263 state_tokens[4] = parse_integer (inst, Program);
1264 if (state_tokens[4] < state_tokens[3]) {
1265 _mesa_set_program_error (ctx, Program->Position,
1266 "Second matrix index less than the first");
1267 _mesa_error (ctx, GL_INVALID_OPERATION,
1268 "Second matrix index (%d) less than the first (%d)",
1269 state_tokens[4], state_tokens[3]);
1270 return 1;
1271 }
1272 }
1273 else {
1274 state_tokens[4] = state_tokens[3];
1275 (*inst)++;
1276 }
1277 break;
1278 }
1279
1280 return 0;
1281}
1282
1283/**
1284 * This parses a state string (rather, the binary version of it) into
1285 * a 6-token similar for the state fetching code in program.c
1286 *
1287 * One might ask, why fetch these parameters into just like you fetch
1288 * state when they are already stored in other places?
1289 *
1290 * Because of array offsets -> We can stick env/local parameters in the
1291 * middle of a parameter array and then index someplace into the array
1292 * when we execute.
1293 *
1294 * One optimization might be to only do this for the cases where the
1295 * env/local parameters end up inside of an array, and leave the
1296 * single parameters (or arrays of pure env/local pareameters) in their
1297 * respective register files.
1298 *
1299 * For ENV parameters, the format is:
1300 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1301 * state_tokens[1] = STATE_ENV
1302 * state_tokens[2] = the parameter index
1303 *
1304 * for LOCAL parameters, the format is:
1305 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1306 * state_tokens[1] = STATE_LOCAL
1307 * state_tokens[2] = the parameter index
1308 *
1309 * \param inst - the start in the binary arry to start working from
1310 * \param state_tokens - the storage for the 6-token state description
1311 * \return - 0 on sucess, 1 on failure
1312 */
1313static GLuint
1314parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
1315 struct arb_program *Program, GLint * state_tokens)
1316{
1317 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1318 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1319 else
1320 state_tokens[0] = STATE_VERTEX_PROGRAM;
1321
1322
1323 switch (*(*inst)++) {
1324 case PROGRAM_PARAM_ENV:
1325 state_tokens[1] = STATE_ENV;
1326 state_tokens[2] = parse_integer (inst, Program);
1327
1328 /* Check state_tokens[2] against the number of ENV parameters available */
1329 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1330 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
1331 ||
1332 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1333 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
1334 _mesa_set_program_error (ctx, Program->Position,
1335 "Invalid Program Env Parameter");
1336 _mesa_error (ctx, GL_INVALID_OPERATION,
1337 "Invalid Program Env Parameter: %d",
1338 state_tokens[2]);
1339 return 1;
1340 }
1341
1342 break;
1343
1344 case PROGRAM_PARAM_LOCAL:
1345 state_tokens[1] = STATE_LOCAL;
1346 state_tokens[2] = parse_integer (inst, Program);
1347
1348 /* Check state_tokens[2] against the number of LOCAL parameters available */
1349 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1350 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
1351 ||
1352 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1353 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
1354 _mesa_set_program_error (ctx, Program->Position,
1355 "Invalid Program Local Parameter");
1356 _mesa_error (ctx, GL_INVALID_OPERATION,
1357 "Invalid Program Local Parameter: %d",
1358 state_tokens[2]);
1359 return 1;
1360 }
1361 break;
1362 }
1363
1364 return 0;
1365}
1366
1367/**
1368 * For ARB_vertex_program, programs are not allowed to use both an explicit
1369 * vertex attribute and a generic vertex attribute corresponding to the same
1370 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1371 *
1372 * This will walk our var_cache and make sure that nobody does anything fishy.
1373 *
1374 * \return 0 on sucess, 1 on error
1375 */
1376static GLuint
1377generic_attrib_check(struct var_cache *vc_head)
1378{
1379 int a;
1380 struct var_cache *curr;
1381 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1382 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1383
1384 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1385 explicitAttrib[a] = GL_FALSE;
1386 genericAttrib[a] = GL_FALSE;
1387 }
1388
1389 curr = vc_head;
1390 while (curr) {
1391 if (curr->type == vt_attrib) {
1392 if (curr->attrib_is_generic)
1393 genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1394 else
1395 explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1396 }
1397
1398 curr = curr->next;
1399 }
1400
1401 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1402 if ((explicitAttrib[a]) && (genericAttrib[a]))
1403 return 1;
1404 }
1405
1406 return 0;
1407}
1408
1409/**
1410 * This will handle the binding side of an ATTRIB var declaration
1411 *
1412 * \param binding - the fragment input register state, defined in nvfragprog.h
1413 * \param binding_idx - the index in the attrib register file that binding is associated with
1414 * \return returns 0 on sucess, 1 on error
1415 *
1416 * See nvfragparse.c for attrib register file layout
1417 */
1418static GLuint
1419parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
1420 struct arb_program *Program, GLuint * binding,
1421 GLuint * binding_idx, GLuint *is_generic)
1422{
1423 GLuint texcoord;
1424 GLint coord;
1425 GLint err = 0;
1426
1427 *is_generic = 0;
1428 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1429 switch (*(*inst)++) {
1430 case FRAGMENT_ATTRIB_COLOR:
1431 err = parse_color_type (ctx, inst, Program, &coord);
1432 *binding = FRAG_ATTRIB_COL0 + coord;
1433 *binding_idx = 1 + coord;
1434 break;
1435
1436 case FRAGMENT_ATTRIB_TEXCOORD:
1437 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1438 *binding = FRAG_ATTRIB_TEX0 + texcoord;
1439 *binding_idx = 4 + texcoord;
1440 break;
1441
1442 case FRAGMENT_ATTRIB_FOGCOORD:
1443 *binding = FRAG_ATTRIB_FOGC;
1444 *binding_idx = 3;
1445 break;
1446
1447 case FRAGMENT_ATTRIB_POSITION:
1448 *binding = FRAG_ATTRIB_WPOS;
1449 *binding_idx = 0;
1450 break;
1451
1452 default:
1453 err = 1;
1454 break;
1455 }
1456 }
1457 else {
1458 switch (*(*inst)++) {
1459 case VERTEX_ATTRIB_POSITION:
1460 *binding = VERT_ATTRIB_POS;
1461 *binding_idx = 0;
1462 break;
1463
1464 case VERTEX_ATTRIB_WEIGHT:
1465 {
1466 GLint weight;
1467
1468 err = parse_weight_num (ctx, inst, Program, &weight);
1469 *binding = VERT_ATTRIB_WEIGHT;
1470 *binding_idx = 1;
1471 }
1472 _mesa_set_program_error (ctx, Program->Position,
1473 "ARB_vertex_blend not supported\n");
1474 _mesa_error (ctx, GL_INVALID_OPERATION,
1475 "ARB_vertex_blend not supported\n");
1476 return 1;
1477 break;
1478
1479 case VERTEX_ATTRIB_NORMAL:
1480 *binding = VERT_ATTRIB_NORMAL;
1481 *binding_idx = 2;
1482 break;
1483
1484 case VERTEX_ATTRIB_COLOR:
1485 {
1486 GLint color;
1487
1488 err = parse_color_type (ctx, inst, Program, &color);
1489 if (color) {
1490 *binding = VERT_ATTRIB_COLOR1;
1491 *binding_idx = 4;
1492 }
1493 else {
1494 *binding = VERT_ATTRIB_COLOR0;
1495 *binding_idx = 3;
1496 }
1497 }
1498 break;
1499
1500 case VERTEX_ATTRIB_FOGCOORD:
1501 *binding = VERT_ATTRIB_FOG;
1502 *binding_idx = 5;
1503 break;
1504
1505 case VERTEX_ATTRIB_TEXCOORD:
1506 {
1507 GLuint unit;
1508
1509 err = parse_texcoord_num (ctx, inst, Program, &unit);
1510 *binding = VERT_ATTRIB_TEX0 + unit;
1511 *binding_idx = 8 + unit;
1512 }
1513 break;
1514
1515 /* It looks like we don't support this at all, atm */
1516 case VERTEX_ATTRIB_MATRIXINDEX:
1517 parse_integer (inst, Program);
1518 _mesa_set_program_error (ctx, Program->Position,
1519 "ARB_palette_matrix not supported");
1520 _mesa_error (ctx, GL_INVALID_OPERATION,
1521 "ARB_palette_matrix not supported");
1522 return 1;
1523 break;
1524
1525 case VERTEX_ATTRIB_GENERIC:
1526 {
1527 GLuint attrib;
1528
1529 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
1530 *is_generic = 1;
1531 switch (attrib) {
1532 case 0:
1533 *binding = VERT_ATTRIB_POS;
1534 break;
1535 case 1:
1536 *binding = VERT_ATTRIB_WEIGHT;
1537 break;
1538 case 2:
1539 *binding = VERT_ATTRIB_NORMAL;
1540 break;
1541 case 3:
1542 *binding = VERT_ATTRIB_COLOR0;
1543 break;
1544 case 4:
1545 *binding = VERT_ATTRIB_COLOR1;
1546 break;
1547 case 5:
1548 *binding = VERT_ATTRIB_FOG;
1549 break;
1550 case 6:
1551 break;
1552 case 7:
1553 break;
1554 default:
1555 *binding = VERT_ATTRIB_TEX0 + (attrib-8);
1556 break;
1557 }
1558 *binding_idx = attrib;
1559 }
1560 }
1561 break;
1562
1563 default:
1564 err = 1;
1565 break;
1566 }
1567 }
1568
1569 /* Can this even happen? */
1570 if (err) {
1571 _mesa_set_program_error (ctx, Program->Position,
1572 "Bad attribute binding");
1573 _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
1574 }
1575
1576 Program->InputsRead |= (1 << *binding_idx);
1577
1578 return err;
1579}
1580
1581/**
1582 * This translates between a binary token for an output variable type
1583 * and the mesa token for the same thing.
1584 *
1585 *
1586 * XXX: What is the 'name' for vertex program state? -> do we need it?
1587 * I don't think we do;
1588 *
1589 * See nvfragprog.h for definitions
1590 *
1591 * \param inst - The parsed tokens
1592 * \param binding - The name of the state we are binding too
1593 * \param binding_idx - The index into the result register file that this is bound too
1594 *
1595 * See nvfragparse.c for the register file layout for fragment programs
1596 * See nvvertparse.c for the register file layout for vertex programs
1597 */
1598static GLuint
1599parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
1600 GLuint * binding_idx, struct arb_program *Program)
1601{
Brian Paulbe76b7f2004-10-04 14:40:05 +00001602 GLuint b, out_color;
Jouk Jansen40322e12004-04-05 08:50:36 +00001603
1604 switch (*(*inst)++) {
1605 case FRAGMENT_RESULT_COLOR:
1606 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
1607 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paulbe76b7f2004-10-04 14:40:05 +00001608 /* This gets result of the color buffer we're supposed to
1609 * draw into
1610 */
1611 parse_output_color_num(ctx, inst, Program, &out_color);
1612
Jouk Jansen40322e12004-04-05 08:50:36 +00001613 *binding = FRAG_OUTPUT_COLR;
Brian Paulbe76b7f2004-10-04 14:40:05 +00001614
1615 /* XXX: We're ignoring the color buffer for now. */
Jouk Jansen40322e12004-04-05 08:50:36 +00001616 *binding_idx = 0;
1617 }
1618 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1619 else {
1620 *binding_idx = 0;
1621 }
1622 break;
1623
1624 case FRAGMENT_RESULT_DEPTH:
1625 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
1626 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1627 *binding = FRAG_OUTPUT_DEPR;
1628 *binding_idx = 2;
1629 }
1630 /* for vtx programs, this is VERTEX_RESULT_COLOR */
1631 else {
1632 GLint color_type;
1633 GLuint face_type = parse_face_type(inst);
1634 GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);
1635
1636 /* back face */
1637 if (face_type) {
1638 if (color_type_ret) return 1;
1639
1640 /* secondary color */
1641 if (color_type) {
1642 *binding_idx = 4;
1643 }
1644 /* primary color */
1645 else {
1646 *binding_idx = 3;
1647 }
1648 }
1649 /* front face */
1650 else {
1651 /* secondary color */
1652 if (color_type) {
1653 *binding_idx = 2;
1654 }
1655 /* primary color */
1656 else {
1657 *binding_idx = 1;
1658 }
1659 }
1660 }
1661 break;
1662
1663 case VERTEX_RESULT_FOGCOORD:
1664 *binding_idx = 5;
1665 break;
1666
1667 case VERTEX_RESULT_POINTSIZE:
1668 *binding_idx = 6;
1669 break;
1670
1671 case VERTEX_RESULT_TEXCOORD:
1672 if (parse_texcoord_num (ctx, inst, Program, &b))
1673 return 1;
1674 *binding_idx = 7 + b;
1675 break;
1676 }
1677
1678 Program->OutputsWritten |= (1 << *binding_idx);
1679
1680 return 0;
1681}
1682
1683/**
1684 * This handles the declaration of ATTRIB variables
1685 *
1686 * XXX: Still needs
1687 * parse_vert_attrib_binding(), or something like that
1688 *
1689 * \return 0 on sucess, 1 on error
1690 */
1691static GLint
1692parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1693 struct arb_program *Program)
1694{
1695 GLuint found;
1696 char *error_msg;
1697 struct var_cache *attrib_var;
1698
1699 attrib_var = parse_string (inst, vc_head, Program, &found);
1700 Program->Position = parse_position (inst);
1701 if (found) {
1702 error_msg = (char *)
1703 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1704 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1705 attrib_var->name);
1706
1707 _mesa_set_program_error (ctx, Program->Position, error_msg);
1708 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1709
1710 _mesa_free (error_msg);
1711 return 1;
1712 }
1713
1714 attrib_var->type = vt_attrib;
1715
1716 /* I think this is ok now - karl */
1717 /* XXX: */
1718 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
1719 {
1720 if (parse_attrib_binding
1721 (ctx, inst, Program, &attrib_var->attrib_binding,
1722 &attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))
1723 return 1;
1724 if (generic_attrib_check(*vc_head)) {
1725 _mesa_set_program_error (ctx, Program->Position,
1726 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
1727 _mesa_error (ctx, GL_INVALID_OPERATION,
1728 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
1729 return 1;
1730 }
1731
1732 }
1733
1734 Program->Base.NumAttributes++;
1735 return 0;
1736}
1737
1738/**
1739 * \param use -- TRUE if we're called when declaring implicit parameters,
1740 * FALSE if we're declaraing variables. This has to do with
1741 * if we get a signed or unsigned float for scalar constants
1742 */
1743static GLuint
1744parse_param_elements (GLcontext * ctx, GLubyte ** inst,
1745 struct var_cache *param_var,
1746 struct arb_program *Program, GLboolean use)
1747{
1748 GLint idx;
1749 GLuint err;
1750 GLint state_tokens[6];
1751 GLfloat const_values[4];
1752
1753 err = 0;
1754
1755 switch (*(*inst)++) {
1756 case PARAM_STATE_ELEMENT:
1757
1758 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1759 return 1;
1760
1761 /* If we adding STATE_MATRIX that has multiple rows, we need to
1762 * unroll it and call _mesa_add_state_reference() for each row
1763 */
1764 if ((state_tokens[0] == STATE_MATRIX)
1765 && (state_tokens[3] != state_tokens[4])) {
1766 GLint row;
1767 GLint first_row = state_tokens[3];
1768 GLint last_row = state_tokens[4];
1769
1770 for (row = first_row; row <= last_row; row++) {
1771 state_tokens[3] = state_tokens[4] = row;
1772
1773 idx =
1774 _mesa_add_state_reference (Program->Parameters,
1775 state_tokens);
1776 if (param_var->param_binding_begin == ~0U)
1777 param_var->param_binding_begin = idx;
1778 param_var->param_binding_length++;
1779 Program->Base.NumParameters++;
1780 }
1781 }
1782 else {
1783 idx =
1784 _mesa_add_state_reference (Program->Parameters, state_tokens);
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 }
1790 break;
1791
1792 case PARAM_PROGRAM_ELEMENT:
1793
1794 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1795 return 1;
1796 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
1797 if (param_var->param_binding_begin == ~0U)
1798 param_var->param_binding_begin = idx;
1799 param_var->param_binding_length++;
1800 Program->Base.NumParameters++;
1801
1802 /* Check if there is more: 0 -> we're done, else its an integer */
1803 if (**inst) {
1804 GLuint out_of_range, new_idx;
1805 GLuint start_idx = state_tokens[2] + 1;
1806 GLuint end_idx = parse_integer (inst, Program);
1807
1808 out_of_range = 0;
1809 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1810 if (((state_tokens[1] == STATE_ENV)
1811 && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
1812 || ((state_tokens[1] == STATE_LOCAL)
1813 && (end_idx >=
1814 ctx->Const.MaxFragmentProgramLocalParams)))
1815 out_of_range = 1;
1816 }
1817 else {
1818 if (((state_tokens[1] == STATE_ENV)
1819 && (end_idx >= ctx->Const.MaxVertexProgramEnvParams))
1820 || ((state_tokens[1] == STATE_LOCAL)
1821 && (end_idx >=
1822 ctx->Const.MaxVertexProgramLocalParams)))
1823 out_of_range = 1;
1824 }
1825 if (out_of_range) {
1826 _mesa_set_program_error (ctx, Program->Position,
1827 "Invalid Program Parameter");
1828 _mesa_error (ctx, GL_INVALID_OPERATION,
1829 "Invalid Program Parameter: %d", end_idx);
1830 return 1;
1831 }
1832
1833 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1834 state_tokens[2] = new_idx;
1835 idx =
1836 _mesa_add_state_reference (Program->Parameters,
1837 state_tokens);
1838 param_var->param_binding_length++;
1839 Program->Base.NumParameters++;
1840 }
1841 }
1842 else
1843 {
1844 (*inst)++;
1845 }
1846 break;
1847
1848 case PARAM_CONSTANT:
1849 parse_constant (inst, const_values, Program, use);
1850 idx =
1851 _mesa_add_named_constant (Program->Parameters,
1852 (char *) param_var->name, const_values);
1853 if (param_var->param_binding_begin == ~0U)
1854 param_var->param_binding_begin = idx;
1855 param_var->param_binding_length++;
1856 Program->Base.NumParameters++;
1857 break;
1858
1859 default:
1860 _mesa_set_program_error (ctx, Program->Position,
1861 "Unexpected token in parse_param_elements()");
1862 _mesa_error (ctx, GL_INVALID_OPERATION,
1863 "Unexpected token in parse_param_elements()");
1864 return 1;
1865 }
1866
1867 /* Make sure we haven't blown past our parameter limits */
1868 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1869 (Program->Base.NumParameters >=
1870 ctx->Const.MaxVertexProgramLocalParams))
1871 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1872 && (Program->Base.NumParameters >=
1873 ctx->Const.MaxFragmentProgramLocalParams))) {
1874 _mesa_set_program_error (ctx, Program->Position,
1875 "Too many parameter variables");
1876 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1877 return 1;
1878 }
1879
1880 return err;
1881}
1882
1883/**
1884 * This picks out PARAM program parameter bindings.
1885 *
1886 * XXX: This needs to be stressed & tested
1887 *
1888 * \return 0 on sucess, 1 on error
1889 */
1890static GLuint
1891parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1892 struct arb_program *Program)
1893{
Brian Paulbd997cd2004-07-20 21:12:56 +00001894 GLuint found, err;
1895 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001896 char *error_msg;
1897 struct var_cache *param_var;
1898
1899 err = 0;
1900 param_var = parse_string (inst, vc_head, Program, &found);
1901 Program->Position = parse_position (inst);
1902
1903 if (found) {
1904 error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
1905 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1906 param_var->name);
1907
1908 _mesa_set_program_error (ctx, Program->Position, error_msg);
1909 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1910
1911 _mesa_free (error_msg);
1912 return 1;
1913 }
1914
1915 specified_length = parse_integer (inst, Program);
1916
1917 if (specified_length < 0) {
1918 _mesa_set_program_error (ctx, Program->Position,
1919 "Negative parameter array length");
1920 _mesa_error (ctx, GL_INVALID_OPERATION,
1921 "Negative parameter array length: %d", specified_length);
1922 return 1;
1923 }
1924
1925 param_var->type = vt_param;
1926 param_var->param_binding_length = 0;
1927
1928 /* Right now, everything is shoved into the main state register file.
1929 *
1930 * In the future, it would be nice to leave things ENV/LOCAL params
1931 * in their respective register files, if possible
1932 */
1933 param_var->param_binding_type = PROGRAM_STATE_VAR;
1934
1935 /* Remember to:
1936 * * - add each guy to the parameter list
1937 * * - increment the param_var->param_binding_len
1938 * * - store the param_var->param_binding_begin for the first one
1939 * * - compare the actual len to the specified len at the end
1940 */
1941 while (**inst != PARAM_NULL) {
1942 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1943 return 1;
1944 }
1945
1946 /* Test array length here! */
1947 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001948 if (specified_length != (int)param_var->param_binding_length) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001949 _mesa_set_program_error (ctx, Program->Position,
1950 "Declared parameter array lenght does not match parameter list");
1951 _mesa_error (ctx, GL_INVALID_OPERATION,
1952 "Declared parameter array lenght does not match parameter list");
1953 }
1954 }
1955
1956 (*inst)++;
1957
1958 return 0;
1959}
1960
1961/**
1962 *
1963 */
1964static GLuint
1965parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1966 struct arb_program *Program, struct var_cache **new_var)
1967{
1968 struct var_cache *param_var;
1969
1970 /* First, insert a dummy entry into the var_cache */
1971 var_cache_create (&param_var);
1972 param_var->name = (GLubyte *) _mesa_strdup (" ");
1973 param_var->type = vt_param;
1974
1975 param_var->param_binding_length = 0;
1976 /* Don't fill in binding_begin; We use the default value of -1
1977 * to tell if its already initialized, elsewhere.
1978 *
1979 * param_var->param_binding_begin = 0;
1980 */
1981 param_var->param_binding_type = PROGRAM_STATE_VAR;
1982
1983 var_cache_append (vc_head, param_var);
1984
1985 /* Then fill it with juicy parameter goodness */
1986 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1987 return 1;
1988
1989 *new_var = param_var;
1990
1991 return 0;
1992}
1993
1994
1995/**
1996 * This handles the declaration of TEMP variables
1997 *
1998 * \return 0 on sucess, 1 on error
1999 */
2000static GLuint
2001parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2002 struct arb_program *Program)
2003{
2004 GLuint found;
2005 struct var_cache *temp_var;
2006 char *error_msg;
2007
2008 while (**inst != 0) {
2009 temp_var = parse_string (inst, vc_head, Program, &found);
2010 Program->Position = parse_position (inst);
2011 if (found) {
2012 error_msg = (char *)
2013 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2014 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2015 temp_var->name);
2016
2017 _mesa_set_program_error (ctx, Program->Position, error_msg);
2018 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2019
2020 _mesa_free (error_msg);
2021 return 1;
2022 }
2023
2024 temp_var->type = vt_temp;
2025
2026 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
2027 (Program->Base.NumTemporaries >=
2028 ctx->Const.MaxFragmentProgramTemps))
2029 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
2030 && (Program->Base.NumTemporaries >=
2031 ctx->Const.MaxVertexProgramTemps))) {
2032 _mesa_set_program_error (ctx, Program->Position,
2033 "Too many TEMP variables declared");
2034 _mesa_error (ctx, GL_INVALID_OPERATION,
2035 "Too many TEMP variables declared");
2036 return 1;
2037 }
2038
2039 temp_var->temp_binding = Program->Base.NumTemporaries;
2040 Program->Base.NumTemporaries++;
2041 }
2042 (*inst)++;
2043
2044 return 0;
2045}
2046
2047/**
2048 * This handles variables of the OUTPUT variety
2049 *
2050 * \return 0 on sucess, 1 on error
2051 */
2052static GLuint
2053parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2054 struct arb_program *Program)
2055{
2056 GLuint found;
2057 struct var_cache *output_var;
2058
2059 output_var = parse_string (inst, vc_head, Program, &found);
2060 Program->Position = parse_position (inst);
2061 if (found) {
2062 char *error_msg;
2063 error_msg = (char *)
2064 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
2065 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2066 output_var->name);
2067
2068 _mesa_set_program_error (ctx, Program->Position, error_msg);
2069 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2070
2071 _mesa_free (error_msg);
2072 return 1;
2073 }
2074
2075 output_var->type = vt_output;
2076 return parse_result_binding (ctx, inst, &output_var->output_binding,
2077 &output_var->output_binding_idx, Program);
2078}
2079
2080/**
2081 * This handles variables of the ALIAS kind
2082 *
2083 * \return 0 on sucess, 1 on error
2084 */
2085static GLuint
2086parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2087 struct arb_program *Program)
2088{
2089 GLuint found;
2090 struct var_cache *temp_var;
2091 char *error_msg;
2092
2093
2094 temp_var = parse_string (inst, vc_head, Program, &found);
2095 Program->Position = parse_position (inst);
2096
2097 if (found) {
2098 error_msg = (char *)
2099 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2100 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2101 temp_var->name);
2102
2103 _mesa_set_program_error (ctx, Program->Position, error_msg);
2104 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2105
2106 _mesa_free (error_msg);
2107 return 1;
2108 }
2109
2110 temp_var->type = vt_alias;
2111 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2112 Program->Position = parse_position (inst);
2113
2114 if (!found)
2115 {
2116 error_msg = (char *)
2117 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2118 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2119 temp_var->alias_binding->name);
2120
2121 _mesa_set_program_error (ctx, Program->Position, error_msg);
2122 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2123
2124 _mesa_free (error_msg);
2125 return 1;
2126 }
2127
2128 return 0;
2129}
2130
2131/**
2132 * This handles variables of the ADDRESS kind
2133 *
2134 * \return 0 on sucess, 1 on error
2135 */
2136static GLuint
2137parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2138 struct arb_program *Program)
2139{
2140 GLuint found;
2141 struct var_cache *temp_var;
2142 char *error_msg;
2143
2144 while (**inst != 0) {
2145 temp_var = parse_string (inst, vc_head, Program, &found);
2146 Program->Position = parse_position (inst);
2147 if (found) {
2148 error_msg = (char *)
2149 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2150 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2151 temp_var->name);
2152
2153 _mesa_set_program_error (ctx, Program->Position, error_msg);
2154 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2155
2156 _mesa_free (error_msg);
2157 return 1;
2158 }
2159
2160 temp_var->type = vt_address;
2161
2162 if (Program->Base.NumAddressRegs >=
2163 ctx->Const.MaxVertexProgramAddressRegs) {
2164 _mesa_set_program_error (ctx, Program->Position,
2165 "Too many ADDRESS variables declared");
2166 _mesa_error (ctx, GL_INVALID_OPERATION,
2167 "Too many ADDRESS variables declared");
2168 return 1;
2169 }
2170
2171 temp_var->address_binding = Program->Base.NumAddressRegs;
2172 Program->Base.NumAddressRegs++;
2173 }
2174 (*inst)++;
2175
2176 return 0;
2177}
2178
2179/**
2180 * Parse a program declaration
2181 *
2182 * \return 0 on sucess, 1 on error
2183 */
2184static GLint
2185parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2186 struct arb_program *Program)
2187{
2188 GLint err = 0;
2189
2190 switch (*(*inst)++) {
2191 case ADDRESS:
2192 err = parse_address (ctx, inst, vc_head, Program);
2193 break;
2194
2195 case ALIAS:
2196 err = parse_alias (ctx, inst, vc_head, Program);
2197 break;
2198
2199 case ATTRIB:
2200 err = parse_attrib (ctx, inst, vc_head, Program);
2201 break;
2202
2203 case OUTPUT:
2204 err = parse_output (ctx, inst, vc_head, Program);
2205 break;
2206
2207 case PARAM:
2208 err = parse_param (ctx, inst, vc_head, Program);
2209 break;
2210
2211 case TEMP:
2212 err = parse_temp (ctx, inst, vc_head, Program);
2213 break;
2214 }
2215
2216 return err;
2217}
2218
2219/**
2220 * Handle the parsing out of a masked destination register
2221 *
2222 * If we are a vertex program, make sure we don't write to
2223 * result.position of we have specified that the program is
2224 * position invariant
2225 *
2226 * \param File - The register file we write to
2227 * \param Index - The register index we write to
2228 * \param WriteMask - The mask controlling which components we write (1->write)
2229 *
2230 * \return 0 on sucess, 1 on error
2231 */
2232static GLuint
2233parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2234 struct var_cache **vc_head, struct arb_program *Program,
Keith Whitwell7c26b612005-04-21 14:46:57 +00002235 GLint * File, GLint * Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002236{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002237 GLuint result, tmp;
Jouk Jansen40322e12004-04-05 08:50:36 +00002238 struct var_cache *dst;
2239
2240 /* We either have a result register specified, or a
2241 * variable that may or may not be writable
2242 */
2243 switch (*(*inst)++) {
2244 case REGISTER_RESULT:
2245 if (parse_result_binding
2246 (ctx, inst, &result, (GLuint *) Index, Program))
2247 return 1;
2248 *File = PROGRAM_OUTPUT;
2249 break;
2250
2251 case REGISTER_ESTABLISHED_NAME:
2252 dst = parse_string (inst, vc_head, Program, &result);
2253 Program->Position = parse_position (inst);
2254
2255 /* If the name has never been added to our symbol table, we're hosed */
2256 if (!result) {
2257 _mesa_set_program_error (ctx, Program->Position,
2258 "0: Undefined variable");
2259 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2260 dst->name);
2261 return 1;
2262 }
2263
2264 switch (dst->type) {
2265 case vt_output:
2266 *File = PROGRAM_OUTPUT;
2267 *Index = dst->output_binding_idx;
2268 break;
2269
2270 case vt_temp:
2271 *File = PROGRAM_TEMPORARY;
2272 *Index = dst->temp_binding;
2273 break;
2274
2275 /* If the var type is not vt_output or vt_temp, no go */
2276 default:
2277 _mesa_set_program_error (ctx, Program->Position,
2278 "Destination register is read only");
2279 _mesa_error (ctx, GL_INVALID_OPERATION,
2280 "Destination register is read only: %s",
2281 dst->name);
2282 return 1;
2283 }
2284 break;
2285
2286 default:
2287 _mesa_set_program_error (ctx, Program->Position,
2288 "Unexpected opcode in parse_masked_dst_reg()");
2289 _mesa_error (ctx, GL_INVALID_OPERATION,
2290 "Unexpected opcode in parse_masked_dst_reg()");
2291 return 1;
2292 }
2293
2294
2295 /* Position invariance test */
2296 /* This test is done now in syntax portion - when position invariance OPTION
2297 is specified, "result.position" rule is disabled so there is no way
2298 to write the position
2299 */
2300 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2301 (*Index == 0)) {
2302 _mesa_set_program_error (ctx, Program->Position,
2303 "Vertex program specified position invariance and wrote vertex position");
2304 _mesa_error (ctx, GL_INVALID_OPERATION,
2305 "Vertex program specified position invariance and wrote vertex position");
2306 }*/
2307
2308 /* And then the mask.
2309 * w,a -> bit 0
2310 * z,b -> bit 1
2311 * y,g -> bit 2
2312 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002313 *
2314 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002315 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002316 tmp = (GLint) *(*inst)++;
2317 *WriteMask = (((tmp>>3) & 0x1) |
2318 ((tmp>>1) & 0x2) |
2319 ((tmp<<1) & 0x4) |
2320 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002321
2322 return 0;
2323}
2324
2325
2326/**
2327 * Handle the parsing of a address register
2328 *
2329 * \param Index - The register index we write to
2330 *
2331 * \return 0 on sucess, 1 on error
2332 */
2333static GLuint
2334parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2335 struct var_cache **vc_head,
2336 struct arb_program *Program, GLint * Index)
2337{
2338 struct var_cache *dst;
2339 GLuint result;
Brian Paula6c423d2004-08-25 15:59:48 +00002340 (void) Index;
Jouk Jansen40322e12004-04-05 08:50:36 +00002341
2342 dst = parse_string (inst, vc_head, Program, &result);
2343 Program->Position = parse_position (inst);
2344
2345 /* If the name has never been added to our symbol table, we're hosed */
2346 if (!result) {
2347 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2348 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2349 dst->name);
2350 return 1;
2351 }
2352
2353 if (dst->type != vt_address) {
2354 _mesa_set_program_error (ctx, Program->Position,
2355 "Variable is not of type ADDRESS");
2356 _mesa_error (ctx, GL_INVALID_OPERATION,
2357 "Variable: %s is not of type ADDRESS", dst->name);
2358 return 1;
2359 }
2360
2361 return 0;
2362}
2363
Brian Paul8e8fa632005-07-01 02:03:33 +00002364#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002365/**
2366 * Handle the parsing out of a masked address register
2367 *
2368 * \param Index - The register index we write to
2369 * \param WriteMask - The mask controlling which components we write (1->write)
2370 *
2371 * \return 0 on sucess, 1 on error
2372 */
2373static GLuint
2374parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2375 struct var_cache **vc_head,
2376 struct arb_program *Program, GLint * Index,
2377 GLboolean * WriteMask)
2378{
2379 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2380 return 1;
2381
2382 /* This should be 0x8 */
2383 (*inst)++;
2384
2385 /* Writemask of .x is implied */
2386 WriteMask[0] = 1;
2387 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2388
2389 return 0;
2390}
Brian Paul8e8fa632005-07-01 02:03:33 +00002391#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002392
2393/**
2394 * Parse out a swizzle mask.
2395 *
2396 * The values in the input stream are:
2397 * COMPONENT_X -> x/r
2398 * COMPONENT_Y -> y/g
2399 * COMPONENT_Z-> z/b
2400 * COMPONENT_W-> w/a
2401 *
2402 * The values in the output mask are:
2403 * 0 -> x/r
2404 * 1 -> y/g
2405 * 2 -> z/b
2406 * 3 -> w/a
2407 *
2408 * The len parameter allows us to grab 4 components for a vector
2409 * swizzle, or just 1 component for a scalar src register selection
2410 */
2411static GLuint
2412parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len)
2413{
2414 GLint a;
2415
2416 for (a = 0; a < 4; a++)
2417 mask[a] = a;
2418
2419 for (a = 0; a < len; a++) {
2420 switch (*(*inst)++) {
2421 case COMPONENT_X:
2422 mask[a] = 0;
2423 break;
2424
2425 case COMPONENT_Y:
2426 mask[a] = 1;
2427 break;
2428
2429 case COMPONENT_Z:
2430 mask[a] = 2;
2431 break;
2432
2433 case COMPONENT_W:
2434 mask[a] = 3;
2435 break;
2436 }
2437 }
2438
2439 return 0;
2440}
2441
2442/**
2443 */
2444static GLuint
2445parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate)
2446{
2447 GLint a;
2448 GLubyte swz;
2449
2450 *Negate = GL_FALSE;
2451 for (a = 0; a < 4; a++) {
Brian Paul05908952004-06-08 15:20:23 +00002452 if (parse_sign (inst) == -1)
Jouk Jansen40322e12004-04-05 08:50:36 +00002453 *Negate = GL_TRUE;
2454
2455 swz = *(*inst)++;
2456
2457 switch (swz) {
2458 case COMPONENT_0:
2459 mask[a] = SWIZZLE_ZERO;
2460 break;
2461 case COMPONENT_1:
2462 mask[a] = SWIZZLE_ONE;
2463 break;
2464 case COMPONENT_X:
2465 mask[a] = SWIZZLE_X;
2466 break;
2467 case COMPONENT_Y:
2468 mask[a] = SWIZZLE_Y;
2469 break;
2470 case COMPONENT_Z:
2471 mask[a] = SWIZZLE_Z;
2472 break;
2473 case COMPONENT_W:
2474 mask[a] = SWIZZLE_W;
2475 break;
2476
2477 }
2478#if 0
2479 if (swz == 0)
2480 mask[a] = SWIZZLE_ZERO;
2481 else if (swz == 1)
2482 mask[a] = SWIZZLE_ONE;
2483 else
2484 mask[a] = swz - 2;
2485#endif
2486
2487 }
2488
2489 return 0;
2490}
2491
2492
2493static GLuint
2494parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2495 struct arb_program *Program, GLint * File, GLint * Index,
2496 GLboolean *IsRelOffset )
2497{
2498 struct var_cache *src;
Brian Paulbd997cd2004-07-20 21:12:56 +00002499 GLuint binding_state, binding_idx, is_generic, found;
2500 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002501
Keith Whitwell7c26b612005-04-21 14:46:57 +00002502 *IsRelOffset = 0;
2503
Jouk Jansen40322e12004-04-05 08:50:36 +00002504 /* And the binding for the src */
2505 switch (*(*inst)++) {
2506 case REGISTER_ATTRIB:
2507 if (parse_attrib_binding
2508 (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))
2509 return 1;
2510 *File = PROGRAM_INPUT;
2511 *Index = binding_idx;
2512
2513 /* We need to insert a dummy variable into the var_cache so we can
2514 * catch generic vertex attrib aliasing errors
2515 */
2516 var_cache_create(&src);
2517 src->type = vt_attrib;
2518 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
2519 src->attrib_binding = binding_state;
2520 src->attrib_binding_idx = binding_idx;
2521 src->attrib_is_generic = is_generic;
2522 var_cache_append(vc_head, src);
2523 if (generic_attrib_check(*vc_head)) {
2524 _mesa_set_program_error (ctx, Program->Position,
2525 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
2526 _mesa_error (ctx, GL_INVALID_OPERATION,
2527 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
2528 return 1;
2529 }
2530 break;
2531
2532 case REGISTER_PARAM:
2533 switch (**inst) {
2534 case PARAM_ARRAY_ELEMENT:
2535 (*inst)++;
2536 src = parse_string (inst, vc_head, Program, &found);
2537 Program->Position = parse_position (inst);
2538
2539 if (!found) {
2540 _mesa_set_program_error (ctx, Program->Position,
2541 "2: Undefined variable");
2542 _mesa_error (ctx, GL_INVALID_OPERATION,
2543 "2: Undefined variable: %s", src->name);
2544 return 1;
2545 }
2546
2547 *File = src->param_binding_type;
2548
2549 switch (*(*inst)++) {
2550 case ARRAY_INDEX_ABSOLUTE:
2551 offset = parse_integer (inst, Program);
2552
2553 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002554 || (offset >= (int)src->param_binding_length)) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002555 _mesa_set_program_error (ctx, Program->Position,
2556 "Index out of range");
2557 _mesa_error (ctx, GL_INVALID_OPERATION,
2558 "Index %d out of range for %s", offset,
2559 src->name);
2560 return 1;
2561 }
2562
2563 *Index = src->param_binding_begin + offset;
2564 break;
2565
2566 case ARRAY_INDEX_RELATIVE:
2567 {
2568 GLint addr_reg_idx, rel_off;
2569
2570 /* First, grab the address regiseter */
2571 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2572 return 1;
2573
2574 /* And the .x */
2575 ((*inst)++);
2576 ((*inst)++);
2577 ((*inst)++);
2578 ((*inst)++);
2579
2580 /* Then the relative offset */
2581 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2582
2583 /* And store it properly */
2584 *Index = src->param_binding_begin + rel_off;
2585 *IsRelOffset = 1;
2586 }
2587 break;
2588 }
2589 break;
2590
2591 default:
2592
2593 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2594 return 1;
2595
2596 *File = src->param_binding_type;
2597 *Index = src->param_binding_begin;
2598 break;
2599 }
2600 break;
2601
2602 case REGISTER_ESTABLISHED_NAME:
2603
2604 src = parse_string (inst, vc_head, Program, &found);
2605 Program->Position = parse_position (inst);
2606
2607 /* If the name has never been added to our symbol table, we're hosed */
2608 if (!found) {
2609 _mesa_set_program_error (ctx, Program->Position,
2610 "3: Undefined variable");
2611 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2612 src->name);
2613 return 1;
2614 }
2615
2616 switch (src->type) {
2617 case vt_attrib:
2618 *File = PROGRAM_INPUT;
2619 *Index = src->attrib_binding_idx;
2620 break;
2621
2622 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2623 case vt_param:
2624 *File = src->param_binding_type;
2625 *Index = src->param_binding_begin;
2626 break;
2627
2628 case vt_temp:
2629 *File = PROGRAM_TEMPORARY;
2630 *Index = src->temp_binding;
2631 break;
2632
2633 /* If the var type is vt_output no go */
2634 default:
2635 _mesa_set_program_error (ctx, Program->Position,
2636 "destination register is read only");
2637 _mesa_error (ctx, GL_INVALID_OPERATION,
2638 "destination register is read only: %s",
2639 src->name);
2640 return 1;
2641 }
2642 break;
2643
2644 default:
2645 _mesa_set_program_error (ctx, Program->Position,
2646 "Unknown token in parse_src_reg");
2647 _mesa_error (ctx, GL_INVALID_OPERATION,
2648 "Unknown token in parse_src_reg");
2649 return 1;
2650 }
2651
2652 return 0;
2653}
2654
2655/**
2656 */
2657static GLuint
Keith Whitwell7c26b612005-04-21 14:46:57 +00002658parse_fp_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
2659 struct var_cache **vc_head, struct arb_program *Program,
2660 struct fp_src_register *reg )
Jouk Jansen40322e12004-04-05 08:50:36 +00002661{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002662
2663 GLint File;
2664 GLint Index;
2665 GLboolean Negate;
2666 GLubyte Swizzle[4];
2667 GLboolean IsRelOffset;
2668
Jouk Jansen40322e12004-04-05 08:50:36 +00002669 /* Grab the sign */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002670 Negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002671
2672 /* And the src reg */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002673 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002674 return 1;
2675
2676 /* finally, the swizzle */
2677 parse_swizzle_mask (inst, Swizzle, 4);
2678
Keith Whitwell7c26b612005-04-21 14:46:57 +00002679 reg->File = File;
2680 reg->Index = Index;
2681 reg->Abs = 0; /* NV only */
2682 reg->NegateAbs = 0; /* NV only */
2683 reg->NegateBase = Negate;
2684 reg->Swizzle = (Swizzle[0] << 0 |
2685 Swizzle[1] << 3 |
2686 Swizzle[2] << 6 |
2687 Swizzle[3] << 9);
2688
Jouk Jansen40322e12004-04-05 08:50:36 +00002689 return 0;
2690}
2691
Jouk Jansen40322e12004-04-05 08:50:36 +00002692
Keith Whitwell7c26b612005-04-21 14:46:57 +00002693static GLuint
2694parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
2695 struct var_cache **vc_head, struct arb_program *Program,
2696 struct fp_dst_register *reg )
2697{
2698 GLint file, idx, mask;
2699
2700 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002701 return 1;
2702
Keith Whitwell7c26b612005-04-21 14:46:57 +00002703 reg->CondMask = 0; /* NV only */
2704 reg->CondSwizzle = 0; /* NV only */
2705 reg->File = file;
2706 reg->Index = idx;
2707 reg->WriteMask = mask;
2708 return 0;
2709}
2710
2711
2712
2713static GLuint
2714parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
2715 struct var_cache **vc_head, struct arb_program *Program,
2716 struct fp_src_register *reg )
2717{
2718
2719 GLint File;
2720 GLint Index;
2721 GLboolean Negate;
2722 GLubyte Swizzle[4];
2723 GLboolean IsRelOffset;
2724
2725 /* Grab the sign */
2726 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2727
2728 /* And the src reg */
2729 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2730 return 1;
2731
2732 /* finally, the swizzle */
Jouk Jansen40322e12004-04-05 08:50:36 +00002733 parse_swizzle_mask (inst, Swizzle, 1);
2734
Keith Whitwell7c26b612005-04-21 14:46:57 +00002735 reg->File = File;
2736 reg->Index = Index;
2737 reg->Abs = 0; /* NV only */
2738 reg->NegateAbs = 0; /* NV only */
2739 reg->NegateBase = Negate;
2740 reg->Swizzle = (Swizzle[0] << 0);
2741
Jouk Jansen40322e12004-04-05 08:50:36 +00002742 return 0;
2743}
2744
Keith Whitwell7c26b612005-04-21 14:46:57 +00002745
Jouk Jansen40322e12004-04-05 08:50:36 +00002746/**
2747 * This is a big mother that handles getting opcodes into the instruction
2748 * and handling the src & dst registers for fragment program instructions
2749 */
2750static GLuint
2751parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2752 struct var_cache **vc_head, struct arb_program *Program,
2753 struct fp_instruction *fp)
2754{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002755 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002756 GLuint texcoord;
2757 GLubyte instClass, type, code;
2758 GLboolean rel;
2759
2760 /* No condition codes in ARB_fp */
2761 fp->UpdateCondRegister = 0;
2762
2763 /* Record the position in the program string for debugging */
2764 fp->StringPos = Program->Position;
2765
Brian Paul140f99f2005-01-19 14:45:23 +00002766 fp->Data = NULL;
2767
Keith Whitwell209b0902005-05-04 11:20:59 +00002768 fp->DstReg.File = 0xf; /* mark as undef */
2769 fp->SrcReg[0].File = 0xf; /* mark as undef */
2770 fp->SrcReg[1].File = 0xf; /* mark as undef */
2771 fp->SrcReg[2].File = 0xf; /* mark as undef */
2772
Jouk Jansen40322e12004-04-05 08:50:36 +00002773 /* OP_ALU_INST or OP_TEX_INST */
2774 instClass = *(*inst)++;
2775
2776 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2777 * OP_TEX_{SAMPLE, KIL}
2778 */
2779 type = *(*inst)++;
2780
2781 /* The actual opcode name */
2782 code = *(*inst)++;
2783
2784 /* Increment the correct count */
2785 switch (instClass) {
2786 case OP_ALU_INST:
2787 Program->NumAluInstructions++;
2788 break;
2789 case OP_TEX_INST:
2790 Program->NumTexInstructions++;
2791 break;
2792 }
2793
2794 fp->Saturate = 0;
2795 fp->Precision = FLOAT32;
2796
2797 fp->DstReg.CondMask = COND_TR;
2798
2799 switch (type) {
2800 case OP_ALU_VECTOR:
2801 switch (code) {
2802 case OP_ABS_SAT:
2803 fp->Saturate = 1;
2804 case OP_ABS:
2805 fp->Opcode = FP_OPCODE_ABS;
2806 break;
2807
2808 case OP_FLR_SAT:
2809 fp->Saturate = 1;
2810 case OP_FLR:
2811 fp->Opcode = FP_OPCODE_FLR;
2812 break;
2813
2814 case OP_FRC_SAT:
2815 fp->Saturate = 1;
2816 case OP_FRC:
2817 fp->Opcode = FP_OPCODE_FRC;
2818 break;
2819
2820 case OP_LIT_SAT:
2821 fp->Saturate = 1;
2822 case OP_LIT:
2823 fp->Opcode = FP_OPCODE_LIT;
2824 break;
2825
2826 case OP_MOV_SAT:
2827 fp->Saturate = 1;
2828 case OP_MOV:
2829 fp->Opcode = FP_OPCODE_MOV;
2830 break;
2831 }
2832
Keith Whitwell7c26b612005-04-21 14:46:57 +00002833 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002834 return 1;
2835
Keith Whitwell7c26b612005-04-21 14:46:57 +00002836 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002837 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002838 break;
2839
2840 case OP_ALU_SCALAR:
2841 switch (code) {
2842 case OP_COS_SAT:
2843 fp->Saturate = 1;
2844 case OP_COS:
2845 fp->Opcode = FP_OPCODE_COS;
2846 break;
2847
2848 case OP_EX2_SAT:
2849 fp->Saturate = 1;
2850 case OP_EX2:
2851 fp->Opcode = FP_OPCODE_EX2;
2852 break;
2853
2854 case OP_LG2_SAT:
2855 fp->Saturate = 1;
2856 case OP_LG2:
2857 fp->Opcode = FP_OPCODE_LG2;
2858 break;
2859
2860 case OP_RCP_SAT:
2861 fp->Saturate = 1;
2862 case OP_RCP:
2863 fp->Opcode = FP_OPCODE_RCP;
2864 break;
2865
2866 case OP_RSQ_SAT:
2867 fp->Saturate = 1;
2868 case OP_RSQ:
2869 fp->Opcode = FP_OPCODE_RSQ;
2870 break;
2871
2872 case OP_SIN_SAT:
2873 fp->Saturate = 1;
2874 case OP_SIN:
2875 fp->Opcode = FP_OPCODE_SIN;
2876 break;
2877
2878 case OP_SCS_SAT:
2879 fp->Saturate = 1;
2880 case OP_SCS:
2881
2882 fp->Opcode = FP_OPCODE_SCS;
2883 break;
2884 }
2885
Keith Whitwell7c26b612005-04-21 14:46:57 +00002886 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002887 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002888
2889 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002890 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002891 break;
2892
2893 case OP_ALU_BINSC:
2894 switch (code) {
2895 case OP_POW_SAT:
2896 fp->Saturate = 1;
2897 case OP_POW:
2898 fp->Opcode = FP_OPCODE_POW;
2899 break;
2900 }
2901
Keith Whitwell7c26b612005-04-21 14:46:57 +00002902 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002903 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002904
Jouk Jansen40322e12004-04-05 08:50:36 +00002905 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002906 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002907 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002908 }
2909 break;
2910
2911
2912 case OP_ALU_BIN:
2913 switch (code) {
2914 case OP_ADD_SAT:
2915 fp->Saturate = 1;
2916 case OP_ADD:
2917 fp->Opcode = FP_OPCODE_ADD;
2918 break;
2919
2920 case OP_DP3_SAT:
2921 fp->Saturate = 1;
2922 case OP_DP3:
2923 fp->Opcode = FP_OPCODE_DP3;
2924 break;
2925
2926 case OP_DP4_SAT:
2927 fp->Saturate = 1;
2928 case OP_DP4:
2929 fp->Opcode = FP_OPCODE_DP4;
2930 break;
2931
2932 case OP_DPH_SAT:
2933 fp->Saturate = 1;
2934 case OP_DPH:
2935 fp->Opcode = FP_OPCODE_DPH;
2936 break;
2937
2938 case OP_DST_SAT:
2939 fp->Saturate = 1;
2940 case OP_DST:
2941 fp->Opcode = FP_OPCODE_DST;
2942 break;
2943
2944 case OP_MAX_SAT:
2945 fp->Saturate = 1;
2946 case OP_MAX:
2947 fp->Opcode = FP_OPCODE_MAX;
2948 break;
2949
2950 case OP_MIN_SAT:
2951 fp->Saturate = 1;
2952 case OP_MIN:
2953 fp->Opcode = FP_OPCODE_MIN;
2954 break;
2955
2956 case OP_MUL_SAT:
2957 fp->Saturate = 1;
2958 case OP_MUL:
2959 fp->Opcode = FP_OPCODE_MUL;
2960 break;
2961
2962 case OP_SGE_SAT:
2963 fp->Saturate = 1;
2964 case OP_SGE:
2965 fp->Opcode = FP_OPCODE_SGE;
2966 break;
2967
2968 case OP_SLT_SAT:
2969 fp->Saturate = 1;
2970 case OP_SLT:
2971 fp->Opcode = FP_OPCODE_SLT;
2972 break;
2973
2974 case OP_SUB_SAT:
2975 fp->Saturate = 1;
2976 case OP_SUB:
2977 fp->Opcode = FP_OPCODE_SUB;
2978 break;
2979
2980 case OP_XPD_SAT:
2981 fp->Saturate = 1;
2982 case OP_XPD:
2983 fp->Opcode = FP_OPCODE_XPD;
2984 break;
2985 }
2986
Keith Whitwell7c26b612005-04-21 14:46:57 +00002987 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002988 return 1;
2989 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002990 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2991 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002992 }
2993 break;
2994
2995 case OP_ALU_TRI:
2996 switch (code) {
2997 case OP_CMP_SAT:
2998 fp->Saturate = 1;
2999 case OP_CMP:
3000 fp->Opcode = FP_OPCODE_CMP;
3001 break;
3002
3003 case OP_LRP_SAT:
3004 fp->Saturate = 1;
3005 case OP_LRP:
3006 fp->Opcode = FP_OPCODE_LRP;
3007 break;
3008
3009 case OP_MAD_SAT:
3010 fp->Saturate = 1;
3011 case OP_MAD:
3012 fp->Opcode = FP_OPCODE_MAD;
3013 break;
3014 }
3015
Keith Whitwell7c26b612005-04-21 14:46:57 +00003016 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003017 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003018
Jouk Jansen40322e12004-04-05 08:50:36 +00003019 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003020 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
3021 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003022 }
3023 break;
3024
3025 case OP_ALU_SWZ:
3026 switch (code) {
3027 case OP_SWZ_SAT:
3028 fp->Saturate = 1;
3029 case OP_SWZ:
3030 fp->Opcode = FP_OPCODE_SWZ;
3031 break;
3032 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003033 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003034 return 1;
3035
Keith Whitwell7c26b612005-04-21 14:46:57 +00003036 {
3037 GLubyte Swizzle[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
3038 GLubyte Negate[4];
3039 GLint File, Index;
3040
3041 if (parse_src_reg(ctx, inst, vc_head, Program, &File, &Index, &rel))
3042 return 1;
3043 parse_extended_swizzle_mask (inst, Swizzle, Negate);
3044 fp->SrcReg[0].File = File;
3045 fp->SrcReg[0].Index = Index;
3046 fp->SrcReg[0].NegateBase = (Negate[0] << 0 |
3047 Negate[1] << 1 |
3048 Negate[2] << 2 |
3049 Negate[3] << 3);
3050 fp->SrcReg[0].Swizzle = (Swizzle[0] << 0 |
3051 Swizzle[1] << 3 |
3052 Swizzle[2] << 6 |
3053 Swizzle[3] << 9);
3054 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003055 break;
3056
3057 case OP_TEX_SAMPLE:
3058 switch (code) {
3059 case OP_TEX_SAT:
3060 fp->Saturate = 1;
3061 case OP_TEX:
3062 fp->Opcode = FP_OPCODE_TEX;
3063 break;
3064
3065 case OP_TXP_SAT:
3066 fp->Saturate = 1;
3067 case OP_TXP:
3068 fp->Opcode = FP_OPCODE_TXP;
3069 break;
3070
3071 case OP_TXB_SAT:
Jouk Jansen40322e12004-04-05 08:50:36 +00003072 fp->Saturate = 1;
3073 case OP_TXB:
3074 fp->Opcode = FP_OPCODE_TXB;
3075 break;
3076 }
3077
Keith Whitwell7c26b612005-04-21 14:46:57 +00003078 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003079 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003080
3081 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003082 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003083
3084 /* texImageUnit */
3085 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
3086 return 1;
3087 fp->TexSrcUnit = texcoord;
3088
3089 /* texTarget */
3090 switch (*(*inst)++) {
3091 case TEXTARGET_1D:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003092 fp->TexSrcIdx = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003093 break;
3094 case TEXTARGET_2D:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003095 fp->TexSrcIdx = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003096 break;
3097 case TEXTARGET_3D:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003098 fp->TexSrcIdx = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003099 break;
3100 case TEXTARGET_RECT:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003101 fp->TexSrcIdx = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003102 break;
3103 case TEXTARGET_CUBE:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003104 fp->TexSrcIdx = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003105 break;
3106 case TEXTARGET_SHADOW1D:
3107 case TEXTARGET_SHADOW2D:
3108 case TEXTARGET_SHADOWRECT:
3109 /* TODO ARB_fragment_program_shadow code */
3110 break;
3111 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003112 Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcIdx);
Jouk Jansen40322e12004-04-05 08:50:36 +00003113 break;
3114
3115 case OP_TEX_KIL:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003116 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003117 return 1;
Keith Whitwell219f3c42005-07-01 17:12:29 +00003118 fp->Opcode = FP_OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003119 break;
3120 }
3121
3122 return 0;
3123}
3124
Keith Whitwell7c26b612005-04-21 14:46:57 +00003125static GLuint
3126parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
3127 struct var_cache **vc_head, struct arb_program *Program,
3128 struct vp_dst_register *reg )
3129{
3130 GLint file, idx, mask;
3131
3132 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3133 return 1;
3134
3135 reg->File = file;
3136 reg->Index = idx;
3137 reg->WriteMask = mask;
3138 return 0;
3139}
3140
3141/**
3142 * Handle the parsing out of a masked address register
3143 *
3144 * \param Index - The register index we write to
3145 * \param WriteMask - The mask controlling which components we write (1->write)
3146 *
3147 * \return 0 on sucess, 1 on error
3148 */
3149static GLuint
3150parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
3151 struct var_cache **vc_head,
3152 struct arb_program *Program,
3153 struct vp_dst_register *reg)
3154{
3155 GLint idx;
3156
3157 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3158 return 1;
3159
3160 /* This should be 0x8 */
3161 (*inst)++;
3162
3163 reg->File = PROGRAM_ADDRESS;
3164 reg->Index = idx;
3165
3166 /* Writemask of .x is implied */
3167 reg->WriteMask = 0x1;
3168 return 0;
3169}
3170
3171/**
3172 */
3173static GLuint
3174parse_vp_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
3175 struct var_cache **vc_head, struct arb_program *Program,
3176 struct vp_src_register *reg )
3177{
3178
3179 GLint File;
3180 GLint Index;
3181 GLboolean Negate;
3182 GLubyte Swizzle[4];
3183 GLboolean IsRelOffset;
3184
3185 /* Grab the sign */
3186 Negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
3187
3188 /* And the src reg */
3189 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3190 return 1;
3191
3192 /* finally, the swizzle */
3193 parse_swizzle_mask (inst, Swizzle, 4);
3194
3195 reg->File = File;
3196 reg->Index = Index;
3197 reg->Swizzle = ((Swizzle[0] << 0) |
3198 (Swizzle[1] << 3) |
3199 (Swizzle[2] << 6) |
3200 (Swizzle[3] << 9));
3201 reg->Negate = Negate;
3202 reg->RelAddr = IsRelOffset;
3203 return 0;
3204}
3205
3206
3207static GLuint
3208parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
3209 struct var_cache **vc_head, struct arb_program *Program,
3210 struct vp_src_register *reg )
3211{
3212
3213 GLint File;
3214 GLint Index;
3215 GLboolean Negate;
3216 GLubyte Swizzle[4];
3217 GLboolean IsRelOffset;
3218
3219 /* Grab the sign */
3220 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3221
3222 /* And the src reg */
3223 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3224 return 1;
3225
3226 /* finally, the swizzle */
3227 parse_swizzle_mask (inst, Swizzle, 1);
3228
3229 reg->File = File;
3230 reg->Index = Index;
3231 reg->Swizzle = (Swizzle[0] << 0);
3232 reg->Negate = Negate;
3233 reg->RelAddr = IsRelOffset;
3234 return 0;
3235}
3236
3237
Jouk Jansen40322e12004-04-05 08:50:36 +00003238/**
3239 * This is a big mother that handles getting opcodes into the instruction
3240 * and handling the src & dst registers for vertex program instructions
3241 */
3242static GLuint
3243parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3244 struct var_cache **vc_head, struct arb_program *Program,
3245 struct vp_instruction *vp)
3246{
3247 GLint a;
3248 GLubyte type, code;
3249
3250 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3251 type = *(*inst)++;
3252
3253 /* The actual opcode name */
3254 code = *(*inst)++;
3255
3256 /* Record the position in the program string for debugging */
3257 vp->StringPos = Program->Position;
Brian Paul140f99f2005-01-19 14:45:23 +00003258 vp->Data = NULL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003259 vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003260 vp->SrcReg[0].Swizzle = SWIZZLE_NOOP;
3261 vp->SrcReg[1].Swizzle = SWIZZLE_NOOP;
3262 vp->SrcReg[2].Swizzle = SWIZZLE_NOOP;
3263 vp->DstReg.WriteMask = 0xf;
Jouk Jansen40322e12004-04-05 08:50:36 +00003264
3265 switch (type) {
3266 /* XXX: */
3267 case OP_ALU_ARL:
3268 vp->Opcode = VP_OPCODE_ARL;
3269
3270 /* Remember to set SrcReg.RelAddr; */
3271
3272 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003273 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003274 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003275
Jouk Jansen40322e12004-04-05 08:50:36 +00003276 vp->DstReg.File = PROGRAM_ADDRESS;
3277
3278 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003279 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003280 return 1;
3281
3282 break;
3283
3284 case OP_ALU_VECTOR:
3285 switch (code) {
3286 case OP_ABS:
3287 vp->Opcode = VP_OPCODE_ABS;
3288 break;
3289 case OP_FLR:
3290 vp->Opcode = VP_OPCODE_FLR;
3291 break;
3292 case OP_FRC:
3293 vp->Opcode = VP_OPCODE_FRC;
3294 break;
3295 case OP_LIT:
3296 vp->Opcode = VP_OPCODE_LIT;
3297 break;
3298 case OP_MOV:
3299 vp->Opcode = VP_OPCODE_MOV;
3300 break;
3301 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003302
3303 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003304 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003305
3306 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003307 return 1;
3308 break;
3309
3310 case OP_ALU_SCALAR:
3311 switch (code) {
3312 case OP_EX2:
3313 vp->Opcode = VP_OPCODE_EX2;
3314 break;
3315 case OP_EXP:
3316 vp->Opcode = VP_OPCODE_EXP;
3317 break;
3318 case OP_LG2:
3319 vp->Opcode = VP_OPCODE_LG2;
3320 break;
3321 case OP_LOG:
3322 vp->Opcode = VP_OPCODE_LOG;
3323 break;
3324 case OP_RCP:
3325 vp->Opcode = VP_OPCODE_RCP;
3326 break;
3327 case OP_RSQ:
3328 vp->Opcode = VP_OPCODE_RSQ;
3329 break;
3330 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003331 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003332 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003333
3334 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003335 return 1;
3336 break;
3337
3338 case OP_ALU_BINSC:
3339 switch (code) {
3340 case OP_POW:
3341 vp->Opcode = VP_OPCODE_POW;
3342 break;
3343 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003344 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003345 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003346
Jouk Jansen40322e12004-04-05 08:50:36 +00003347 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003348 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003349 return 1;
3350 }
3351 break;
3352
3353 case OP_ALU_BIN:
3354 switch (code) {
3355 case OP_ADD:
3356 vp->Opcode = VP_OPCODE_ADD;
3357 break;
3358 case OP_DP3:
3359 vp->Opcode = VP_OPCODE_DP3;
3360 break;
3361 case OP_DP4:
3362 vp->Opcode = VP_OPCODE_DP4;
3363 break;
3364 case OP_DPH:
3365 vp->Opcode = VP_OPCODE_DPH;
3366 break;
3367 case OP_DST:
3368 vp->Opcode = VP_OPCODE_DST;
3369 break;
3370 case OP_MAX:
3371 vp->Opcode = VP_OPCODE_MAX;
3372 break;
3373 case OP_MIN:
3374 vp->Opcode = VP_OPCODE_MIN;
3375 break;
3376 case OP_MUL:
3377 vp->Opcode = VP_OPCODE_MUL;
3378 break;
3379 case OP_SGE:
3380 vp->Opcode = VP_OPCODE_SGE;
3381 break;
3382 case OP_SLT:
3383 vp->Opcode = VP_OPCODE_SLT;
3384 break;
3385 case OP_SUB:
3386 vp->Opcode = VP_OPCODE_SUB;
3387 break;
3388 case OP_XPD:
3389 vp->Opcode = VP_OPCODE_XPD;
3390 break;
3391 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003392 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003393 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003394
Jouk Jansen40322e12004-04-05 08:50:36 +00003395 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003396 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003397 return 1;
3398 }
3399 break;
3400
3401 case OP_ALU_TRI:
3402 switch (code) {
3403 case OP_MAD:
3404 vp->Opcode = VP_OPCODE_MAD;
3405 break;
3406 }
3407
Keith Whitwell7c26b612005-04-21 14:46:57 +00003408 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003409 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003410
Jouk Jansen40322e12004-04-05 08:50:36 +00003411 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003412 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003413 return 1;
3414 }
3415 break;
3416
3417 case OP_ALU_SWZ:
3418 switch (code) {
3419 case OP_SWZ:
3420 vp->Opcode = VP_OPCODE_SWZ;
3421 break;
3422 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003423 {
3424 GLubyte Swizzle[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
3425 GLubyte Negate[4];
3426 GLboolean RelAddr;
3427 GLint File, Index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003428
Keith Whitwell7c26b612005-04-21 14:46:57 +00003429 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3430 return 1;
3431
3432 if (parse_src_reg(ctx, inst, vc_head, Program, &File, &Index, &RelAddr))
3433 return 1;
3434 parse_extended_swizzle_mask (inst, Swizzle, Negate);
3435 vp->SrcReg[0].File = File;
3436 vp->SrcReg[0].Index = Index;
3437 vp->SrcReg[0].Negate = (Negate[0] << 0 |
3438 Negate[1] << 1 |
3439 Negate[2] << 2 |
3440 Negate[3] << 3);
3441 vp->SrcReg[0].Swizzle = (Swizzle[0] << 0 |
3442 Swizzle[1] << 3 |
3443 Swizzle[2] << 6 |
3444 Swizzle[3] << 9);
3445 vp->SrcReg[0].RelAddr = RelAddr;
3446 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003447 break;
3448 }
3449 return 0;
3450}
3451
3452#if DEBUG_PARSING
3453
3454static GLvoid
3455print_state_token (GLint token)
3456{
3457 switch (token) {
3458 case STATE_MATERIAL:
3459 fprintf (stderr, "STATE_MATERIAL ");
3460 break;
3461 case STATE_LIGHT:
3462 fprintf (stderr, "STATE_LIGHT ");
3463 break;
3464
3465 case STATE_LIGHTMODEL_AMBIENT:
3466 fprintf (stderr, "STATE_AMBIENT ");
3467 break;
3468
3469 case STATE_LIGHTMODEL_SCENECOLOR:
3470 fprintf (stderr, "STATE_SCENECOLOR ");
3471 break;
3472
3473 case STATE_LIGHTPROD:
3474 fprintf (stderr, "STATE_LIGHTPROD ");
3475 break;
3476
3477 case STATE_TEXGEN:
3478 fprintf (stderr, "STATE_TEXGEN ");
3479 break;
3480
3481 case STATE_FOG_COLOR:
3482 fprintf (stderr, "STATE_FOG_COLOR ");
3483 break;
3484
3485 case STATE_FOG_PARAMS:
3486 fprintf (stderr, "STATE_FOG_PARAMS ");
3487 break;
3488
3489 case STATE_CLIPPLANE:
3490 fprintf (stderr, "STATE_CLIPPLANE ");
3491 break;
3492
3493 case STATE_POINT_SIZE:
3494 fprintf (stderr, "STATE_POINT_SIZE ");
3495 break;
3496
3497 case STATE_POINT_ATTENUATION:
3498 fprintf (stderr, "STATE_ATTENUATION ");
3499 break;
3500
3501 case STATE_MATRIX:
3502 fprintf (stderr, "STATE_MATRIX ");
3503 break;
3504
3505 case STATE_MODELVIEW:
3506 fprintf (stderr, "STATE_MODELVIEW ");
3507 break;
3508
3509 case STATE_PROJECTION:
3510 fprintf (stderr, "STATE_PROJECTION ");
3511 break;
3512
3513 case STATE_MVP:
3514 fprintf (stderr, "STATE_MVP ");
3515 break;
3516
3517 case STATE_TEXTURE:
3518 fprintf (stderr, "STATE_TEXTURE ");
3519 break;
3520
3521 case STATE_PROGRAM:
3522 fprintf (stderr, "STATE_PROGRAM ");
3523 break;
3524
3525 case STATE_MATRIX_INVERSE:
3526 fprintf (stderr, "STATE_INVERSE ");
3527 break;
3528
3529 case STATE_MATRIX_TRANSPOSE:
3530 fprintf (stderr, "STATE_TRANSPOSE ");
3531 break;
3532
3533 case STATE_MATRIX_INVTRANS:
3534 fprintf (stderr, "STATE_INVTRANS ");
3535 break;
3536
3537 case STATE_AMBIENT:
3538 fprintf (stderr, "STATE_AMBIENT ");
3539 break;
3540
3541 case STATE_DIFFUSE:
3542 fprintf (stderr, "STATE_DIFFUSE ");
3543 break;
3544
3545 case STATE_SPECULAR:
3546 fprintf (stderr, "STATE_SPECULAR ");
3547 break;
3548
3549 case STATE_EMISSION:
3550 fprintf (stderr, "STATE_EMISSION ");
3551 break;
3552
3553 case STATE_SHININESS:
3554 fprintf (stderr, "STATE_SHININESS ");
3555 break;
3556
3557 case STATE_HALF:
3558 fprintf (stderr, "STATE_HALF ");
3559 break;
3560
3561 case STATE_POSITION:
3562 fprintf (stderr, "STATE_POSITION ");
3563 break;
3564
3565 case STATE_ATTENUATION:
3566 fprintf (stderr, "STATE_ATTENUATION ");
3567 break;
3568
3569 case STATE_SPOT_DIRECTION:
3570 fprintf (stderr, "STATE_DIRECTION ");
3571 break;
3572
3573 case STATE_TEXGEN_EYE_S:
3574 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3575 break;
3576
3577 case STATE_TEXGEN_EYE_T:
3578 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3579 break;
3580
3581 case STATE_TEXGEN_EYE_R:
3582 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3583 break;
3584
3585 case STATE_TEXGEN_EYE_Q:
3586 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3587 break;
3588
3589 case STATE_TEXGEN_OBJECT_S:
3590 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3591 break;
3592
3593 case STATE_TEXGEN_OBJECT_T:
3594 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3595 break;
3596
3597 case STATE_TEXGEN_OBJECT_R:
3598 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3599 break;
3600
3601 case STATE_TEXGEN_OBJECT_Q:
3602 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3603 break;
3604
3605 case STATE_TEXENV_COLOR:
3606 fprintf (stderr, "STATE_TEXENV_COLOR ");
3607 break;
3608
3609 case STATE_DEPTH_RANGE:
3610 fprintf (stderr, "STATE_DEPTH_RANGE ");
3611 break;
3612
3613 case STATE_VERTEX_PROGRAM:
3614 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3615 break;
3616
3617 case STATE_FRAGMENT_PROGRAM:
3618 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3619 break;
3620
3621 case STATE_ENV:
3622 fprintf (stderr, "STATE_ENV ");
3623 break;
3624
3625 case STATE_LOCAL:
3626 fprintf (stderr, "STATE_LOCAL ");
3627 break;
3628
3629 }
3630 fprintf (stderr, "[%d] ", token);
3631}
3632
3633
3634static GLvoid
3635debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3636 struct arb_program *Program)
3637{
3638 struct var_cache *vc;
3639 GLint a, b;
3640
3641 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3642
3643 /* First of all, print out the contents of the var_cache */
3644 vc = vc_head;
3645 while (vc) {
3646 fprintf (stderr, "[%x]\n", vc);
3647 switch (vc->type) {
3648 case vt_none:
3649 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3650 break;
3651 case vt_attrib:
3652 fprintf (stderr, "ATTRIB %s\n", vc->name);
3653 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3654 break;
3655 case vt_param:
3656 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3657 vc->param_binding_begin, vc->param_binding_length);
3658 b = vc->param_binding_begin;
3659 for (a = 0; a < vc->param_binding_length; a++) {
3660 fprintf (stderr, "%s\n",
3661 Program->Parameters->Parameters[a + b].Name);
3662 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3663 print_state_token (Program->Parameters->Parameters[a + b].
3664 StateIndexes[0]);
3665 print_state_token (Program->Parameters->Parameters[a + b].
3666 StateIndexes[1]);
3667 print_state_token (Program->Parameters->Parameters[a + b].
3668 StateIndexes[2]);
3669 print_state_token (Program->Parameters->Parameters[a + b].
3670 StateIndexes[3]);
3671 print_state_token (Program->Parameters->Parameters[a + b].
3672 StateIndexes[4]);
3673 print_state_token (Program->Parameters->Parameters[a + b].
3674 StateIndexes[5]);
3675 }
3676 else
3677 fprintf (stderr, "%f %f %f %f\n",
3678 Program->Parameters->Parameters[a + b].Values[0],
3679 Program->Parameters->Parameters[a + b].Values[1],
3680 Program->Parameters->Parameters[a + b].Values[2],
3681 Program->Parameters->Parameters[a + b].Values[3]);
3682 }
3683 break;
3684 case vt_temp:
3685 fprintf (stderr, "TEMP %s\n", vc->name);
3686 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3687 break;
3688 case vt_output:
3689 fprintf (stderr, "OUTPUT %s\n", vc->name);
3690 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3691 break;
3692 case vt_alias:
3693 fprintf (stderr, "ALIAS %s\n", vc->name);
3694 fprintf (stderr, " binding: 0x%x (%s)\n",
3695 vc->alias_binding, vc->alias_binding->name);
3696 break;
3697 }
3698 vc = vc->next;
3699 }
3700}
3701
3702#endif
3703
3704
3705/**
3706 * The main loop for parsing a fragment or vertex program
3707 *
3708 * \return 0 on sucess, 1 on error
3709 */
3710static GLint
3711parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3712 struct arb_program *Program)
3713{
3714 GLint err = 0;
3715
3716 Program->MajorVersion = (GLuint) * inst++;
3717 Program->MinorVersion = (GLuint) * inst++;
3718
3719 while (*inst != END) {
3720 switch (*inst++) {
3721
3722 case OPTION:
3723 switch (*inst++) {
3724 case ARB_PRECISION_HINT_FASTEST:
3725 Program->PrecisionOption = GL_FASTEST;
3726 break;
3727
3728 case ARB_PRECISION_HINT_NICEST:
3729 Program->PrecisionOption = GL_NICEST;
3730 break;
3731
3732 case ARB_FOG_EXP:
3733 Program->FogOption = GL_EXP;
3734 break;
3735
3736 case ARB_FOG_EXP2:
3737 Program->FogOption = GL_EXP2;
3738 break;
3739
3740 case ARB_FOG_LINEAR:
3741 Program->FogOption = GL_LINEAR;
3742 break;
3743
3744 case ARB_POSITION_INVARIANT:
3745 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
3746 Program->HintPositionInvariant = 1;
3747 break;
3748
3749 case ARB_FRAGMENT_PROGRAM_SHADOW:
3750 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3751 /* TODO ARB_fragment_program_shadow code */
3752 }
3753 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003754
3755 case ARB_DRAW_BUFFERS:
3756 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3757 /* do nothing for now */
3758 }
3759 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003760 }
3761 break;
3762
3763 case INSTRUCTION:
3764 Program->Position = parse_position (&inst);
3765
3766 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3767
3768 /* Check the instruction count
3769 * XXX: Does END count as an instruction?
3770 */
3771 if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
3772 _mesa_set_program_error (ctx, Program->Position,
3773 "Max instruction count exceeded!");
3774 _mesa_error (ctx, GL_INVALID_OPERATION,
3775 "Max instruction count exceeded!");
3776 }
3777
3778 /* Realloc Program->FPInstructions */
3779 Program->FPInstructions =
3780 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
3781 Program->Base.NumInstructions*sizeof(struct fp_instruction),
3782 (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction));
3783
3784 /* parse the current instruction */
3785 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
3786 &Program->FPInstructions[Program->Base.NumInstructions]);
3787
3788 }
3789 else {
3790 /* Check the instruction count
3791 * XXX: Does END count as an instruction?
3792 */
3793 if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
3794 _mesa_set_program_error (ctx, Program->Position,
3795 "Max instruction count exceeded!");
3796 _mesa_error (ctx, GL_INVALID_OPERATION,
3797 "Max instruction count exceeded!");
3798 }
3799
3800 /* Realloc Program->VPInstructions */
3801 Program->VPInstructions =
3802 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
3803 Program->Base.NumInstructions*sizeof(struct vp_instruction),
3804 (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction));
3805
3806 /* parse the current instruction */
3807 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
3808 &Program->VPInstructions[Program->Base.NumInstructions]);
3809 }
3810
3811 /* increment Program->Base.NumInstructions */
3812 Program->Base.NumInstructions++;
3813 break;
3814
3815 case DECLARATION:
3816 err = parse_declaration (ctx, &inst, vc_head, Program);
3817 break;
3818
3819 default:
3820 break;
3821 }
3822
3823 if (err)
3824 break;
3825 }
3826
3827 /* Finally, tag on an OPCODE_END instruction */
3828 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3829 Program->FPInstructions =
3830 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
3831 Program->Base.NumInstructions*sizeof(struct fp_instruction),
3832 (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
3833
3834 Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
Keith Whitwell209b0902005-05-04 11:20:59 +00003835 Program->FPInstructions[Program->Base.NumInstructions].Saturate = 0;
3836 Program->FPInstructions[Program->Base.NumInstructions].DstReg.File = 0xf;
3837 Program->FPInstructions[Program->Base.NumInstructions].SrcReg[0].File = 0xf;
3838 Program->FPInstructions[Program->Base.NumInstructions].SrcReg[1].File = 0xf;
3839 Program->FPInstructions[Program->Base.NumInstructions].SrcReg[2].File = 0xf;
Jouk Jansen40322e12004-04-05 08:50:36 +00003840 /* YYY Wrong Position in program, whatever, at least not random -> crash
3841 Program->Position = parse_position (&inst);
3842 */
3843 Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
Brian Paul140f99f2005-01-19 14:45:23 +00003844 Program->FPInstructions[Program->Base.NumInstructions].Data = NULL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003845 }
3846 else {
3847 Program->VPInstructions =
3848 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
3849 Program->Base.NumInstructions*sizeof(struct vp_instruction),
3850 (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
3851
3852 Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
3853 /* YYY Wrong Position in program, whatever, at least not random -> crash
3854 Program->Position = parse_position (&inst);
3855 */
3856 Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
Brian Paul140f99f2005-01-19 14:45:23 +00003857 Program->VPInstructions[Program->Base.NumInstructions].Data = NULL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003858 }
3859
3860 /* increment Program->Base.NumInstructions */
3861 Program->Base.NumInstructions++;
3862
3863 return err;
3864}
3865
3866/* XXX temporary */
Brian Paula6c423d2004-08-25 15:59:48 +00003867__extension__ static char core_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +00003868#include "grammar_syn.h"
3869;
3870
3871static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3872{
3873 char error_msg[300];
3874 GLint error_pos;
3875
3876 if (grammar_set_reg8 (id, name, value))
3877 return 0;
3878
3879 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3880 _mesa_set_program_error (ctx, error_pos, error_msg);
3881 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3882 return 1;
3883}
3884
3885static int extension_is_supported (const GLubyte *ext)
3886{
Adam Jackson94987be2004-10-24 02:05:40 +00003887 const GLubyte *extensions = GL_CALL(GetString)(GL_EXTENSIONS);
Jouk Jansen40322e12004-04-05 08:50:36 +00003888 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
Karl Schultz6258b762005-05-05 21:08:07 +00003889 const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
Jouk Jansen40322e12004-04-05 08:50:36 +00003890
3891 while (extensions < end)
3892 {
3893 const GLubyte *name_end = (const GLubyte *) strchr ((const char *) extensions, ' ');
3894 if (name_end == NULL)
3895 name_end = end;
3896 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3897 (const char *) extensions, ext_len) == 0)
3898 return 1;
3899 extensions = name_end + 1;
3900 }
3901
3902 return 0;
3903}
3904
3905static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3906{
3907 if (extension_is_supported (extname))
3908 if (set_reg8 (ctx, id, name, 0x01))
3909 return 1;
3910 return 0;
3911}
3912
3913/**
3914 * This kicks everything off.
3915 *
3916 * \param ctx - The GL Context
3917 * \param str - The program string
3918 * \param len - The program string length
3919 * \param Program - The arb_program struct to return all the parsed info in
3920 * \return 0 on sucess, 1 on error
3921 */
3922GLuint
3923_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3924 struct arb_program * program)
3925{
3926 GLint a, err, error_pos;
3927 char error_msg[300];
3928 GLuint parsed_len;
3929 struct var_cache *vc_head;
3930 grammar arbprogram_syn_id;
3931 GLubyte *parsed, *inst;
3932 GLubyte *strz = NULL;
3933 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3934
Brian Paul7f76b8f2004-09-10 01:05:39 +00003935 /* Reset error state */
3936 _mesa_set_program_error(ctx, -1, NULL);
3937
Jouk Jansen40322e12004-04-05 08:50:36 +00003938#if DEBUG_PARSING
3939 fprintf (stderr, "Loading grammar text!\n");
3940#endif
3941
3942 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3943 if (!arbprogram_syn_is_ok) {
3944 grammar grammar_syn_id;
3945 GLint err;
3946 GLuint parsed_len;
3947 byte *parsed;
3948
3949 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3950 if (grammar_syn_id == 0) {
3951 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3952 _mesa_set_program_error (ctx, error_pos, error_msg);
3953 _mesa_error (ctx, GL_INVALID_OPERATION,
3954 "Error loading grammar rule set");
3955 return 1;
3956 }
3957
3958 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3959
3960 /* NOTE: we cant destroy grammar_syn_id right here because grammar_destroy() can
3961 reset the last error
3962 */
3963
3964 if (err == 0) {
3965 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3966 _mesa_set_program_error (ctx, error_pos, error_msg);
3967 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3968
3969 grammar_destroy (grammar_syn_id);
3970 return 1;
3971 }
3972
3973 grammar_destroy (grammar_syn_id);
3974
3975 arbprogram_syn_is_ok = 1;
3976 }
3977
3978 /* create the grammar object */
3979 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3980 if (arbprogram_syn_id == 0) {
3981 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3982 _mesa_set_program_error (ctx, error_pos, error_msg);
3983 _mesa_error (ctx, GL_INVALID_OPERATION,
3984 "Error loading grammer rule set");
3985 return 1;
3986 }
3987
3988 /* Set program_target register value */
3989 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3990 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3991 grammar_destroy (arbprogram_syn_id);
3992 return 1;
3993 }
3994
3995 /* Enable all active extensions */
3996 if (enable_ext (ctx, arbprogram_syn_id,
3997 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3998 enable_ext (ctx, arbprogram_syn_id,
3999 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
4000 enable_ext (ctx, arbprogram_syn_id,
4001 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
4002 enable_ext (ctx, arbprogram_syn_id,
4003 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
4004 enable_ext (ctx, arbprogram_syn_id,
4005 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
4006 enable_ext (ctx, arbprogram_syn_id,
4007 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
4008 enable_ext (ctx, arbprogram_syn_id,
4009 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
4010 enable_ext (ctx, arbprogram_syn_id,
Brian Pauledfe0fe2004-08-20 14:21:20 +00004011 (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
4012 enable_ext (ctx, arbprogram_syn_id,
Jouk Jansen40322e12004-04-05 08:50:36 +00004013 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
4014 enable_ext (ctx, arbprogram_syn_id,
4015 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
4016 enable_ext (ctx, arbprogram_syn_id,
Michal Krolad22ce82004-10-11 08:13:25 +00004017 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
4018 enable_ext (ctx, arbprogram_syn_id,
4019 (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
Jouk Jansen40322e12004-04-05 08:50:36 +00004020 grammar_destroy (arbprogram_syn_id);
4021 return 1;
4022 }
4023
4024 /* check for NULL character occurences */
4025 {
4026 int i;
4027 for (i = 0; i < len; i++)
4028 if (str[i] == '\0') {
4029 _mesa_set_program_error (ctx, i, "invalid character");
4030 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
4031
4032 grammar_destroy (arbprogram_syn_id);
4033 return 1;
4034 }
4035 }
4036
4037 /* copy the program string to a null-terminated string */
4038 /* XXX should I check for NULL from malloc()? */
Brian Paulbdd15b52004-05-04 15:11:06 +00004039 strz = (GLubyte *) _mesa_malloc (len + 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00004040 _mesa_memcpy (strz, str, len);
4041 strz[len] = '\0';
4042
4043#if DEBUG_PARSING
4044 printf ("Checking Grammar!\n");
4045#endif
Michal Krolb80bc052004-10-21 14:09:54 +00004046 /* do a fast check on program string - initial production buffer is 4K */
4047 err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00004048
4049 /* Syntax parse error */
4050 if (err == 0) {
4051 _mesa_free (strz);
4052 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
4053 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul5fe90292004-07-20 21:15:13 +00004054 _mesa_error (ctx, GL_INVALID_OPERATION, "glProgramStringARB(syntax error)");
4055
4056 /* useful for debugging */
4057 if (0) {
4058 int line, col;
4059 char *s;
Brian Paul17386de2004-08-22 17:24:27 +00004060 printf("Program: %s\n", (char *) strz);
Brian Paul5fe90292004-07-20 21:15:13 +00004061 printf("Error Pos: %d\n", ctx->Program.ErrorPos);
4062 s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos, &line, &col);
4063 printf("line %d col %d: %s\n", line, col, s);
4064 }
4065
Jouk Jansen40322e12004-04-05 08:50:36 +00004066 grammar_destroy (arbprogram_syn_id);
4067 return 1;
4068 }
4069
4070#if DEBUG_PARSING
4071 printf ("Destroying grammer dict [parse retval: %d]\n", err);
4072#endif
4073 grammar_destroy (arbprogram_syn_id);
4074
4075 /* Initialize the arb_program struct */
4076 program->Base.String = strz;
4077 program->Base.NumInstructions =
4078 program->Base.NumTemporaries =
4079 program->Base.NumParameters =
4080 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
4081 program->Parameters = _mesa_new_parameter_list ();
4082 program->InputsRead = 0;
4083 program->OutputsWritten = 0;
4084 program->Position = 0;
4085 program->MajorVersion = program->MinorVersion = 0;
4086 program->PrecisionOption = GL_DONT_CARE;
4087 program->FogOption = GL_NONE;
4088 program->HintPositionInvariant = GL_FALSE;
4089 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
4090 program->TexturesUsed[a] = 0;
4091 program->NumAluInstructions =
4092 program->NumTexInstructions =
4093 program->NumTexIndirections = 0;
4094
4095 program->FPInstructions = NULL;
4096 program->VPInstructions = NULL;
4097
4098 vc_head = NULL;
4099 err = 0;
4100
4101 /* Start examining the tokens in the array */
4102 inst = parsed;
4103
4104 /* Check the grammer rev */
4105 if (*inst++ != REVISION) {
4106 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
Brian Paul5fe90292004-07-20 21:15:13 +00004107 _mesa_error (ctx, GL_INVALID_OPERATION, "glProgramStringARB(Grammar verison mismatch)");
Jouk Jansen40322e12004-04-05 08:50:36 +00004108 err = 1;
4109 }
4110 else {
Michal Krolb80bc052004-10-21 14:09:54 +00004111 /* ignore program target */
4112 inst++;
Jouk Jansen40322e12004-04-05 08:50:36 +00004113
4114 err = parse_arb_program (ctx, inst, &vc_head, program);
4115#if DEBUG_PARSING
4116 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
4117#endif
4118 }
4119
4120 /*debug_variables(ctx, vc_head, program); */
4121
4122 /* We're done with the parsed binary array */
4123 var_cache_destroy (&vc_head);
4124
4125 _mesa_free (parsed);
4126#if DEBUG_PARSING
4127 printf ("_mesa_parse_arb_program() done\n");
4128#endif
4129 return err;
4130}