blob: 9e7c9e444d40659799f3e418b022de8d563e1379 [file] [log] [blame]
Ian Romanick770cebb2009-07-20 17:44:36 -07001%{
2/*
3 * Copyright © 2009 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "main/mtypes.h"
Ian Romanickef80c202009-07-22 17:13:08 -070029#include "main/imports.h"
30#include "program.h"
Ian Romanick770cebb2009-07-20 17:44:36 -070031#include "prog_parameter.h"
32#include "prog_parameter_layout.h"
33#include "prog_statevars.h"
34#include "prog_instruction.h"
35
36#include "symbol_table.h"
37#include "program_parser.h"
38
39extern void *yy_scan_string(char *);
40extern void yy_delete_buffer(void *);
41
42static struct asm_symbol *declare_variable(struct asm_parser_state *state,
43 char *name, enum asm_type t, struct YYLTYPE *locp);
44
Ian Romanickef80c202009-07-22 17:13:08 -070045static int add_state_reference(struct gl_program_parameter_list *param_list,
46 const gl_state_index tokens[STATE_LENGTH]);
47
Ian Romanick770cebb2009-07-20 17:44:36 -070048static int initialize_symbol_from_state(struct gl_program *prog,
49 struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
50
51static int initialize_symbol_from_param(struct gl_program *prog,
52 struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
53
54static int initialize_symbol_from_const(struct gl_program *prog,
55 struct asm_symbol *param_var, const struct asm_vector *vec);
56
57static int yyparse(struct asm_parser_state *state);
58
Ian Romanickef80c202009-07-22 17:13:08 -070059static char *make_error_string(const char *fmt, ...);
60
Ian Romanick770cebb2009-07-20 17:44:36 -070061static void yyerror(struct YYLTYPE *locp, struct asm_parser_state *state,
62 const char *s);
63
64static int validate_inputs(struct YYLTYPE *locp,
65 struct asm_parser_state *state);
66
67static void init_dst_reg(struct prog_dst_register *r);
68
69static void init_src_reg(struct asm_src_register *r);
70
71static struct asm_instruction *asm_instruction_ctor(gl_inst_opcode op,
72 const struct prog_dst_register *dst, const struct asm_src_register *src0,
73 const struct asm_src_register *src1, const struct asm_src_register *src2);
74
75#ifndef FALSE
76#define FALSE 0
77#define TRUE (!FALSE)
78#endif
79
80#define YYLLOC_DEFAULT(Current, Rhs, N) \
81 do { \
82 if (YYID(N)) { \
83 (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
84 (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
85 (Current).position = YYRHSLOC(Rhs, 1).position; \
86 (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
87 (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
88 } else { \
89 (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
90 (Current).last_line = (Current).first_line; \
91 (Current).first_column = YYRHSLOC(Rhs, 0).last_column; \
92 (Current).last_column = (Current).first_column; \
93 (Current).position = YYRHSLOC(Rhs, 0).position \
94 + (Current).first_column; \
95 } \
96 } while(YYID(0))
97
98#define YYLEX_PARAM state->scanner
99%}
100
101%pure-parser
102%locations
103%parse-param { struct asm_parser_state *state }
104%error-verbose
105%lex-param { void *scanner }
106
107%union {
108 struct asm_instruction *inst;
109 struct asm_symbol *sym;
110 struct asm_symbol temp_sym;
111 struct asm_swizzle_mask swiz_mask;
112 struct asm_src_register src_reg;
113 struct prog_dst_register dst_reg;
114 struct prog_instruction temp_inst;
115 char *string;
116 unsigned result;
117 unsigned attrib;
118 int integer;
119 float real;
120 unsigned state[5];
121 int negate;
122 struct asm_vector vector;
123 gl_inst_opcode opcode;
124}
125
126%token ARBvp_10 ARBfp_10
127
128/* Tokens for assembler pseudo-ops */
129%token <integer> ADDRESS
130%token ALIAS ATTRIB
131%token OPTION OUTPUT
132%token PARAM
133%token <integer> TEMP
134%token END
135
136 /* Tokens for instructions */
137%token <temp_inst> BIN_OP BINSC_OP SAMPLE_OP SCALAR_OP TRI_OP VECTOR_OP
138%token <temp_inst> ARL KIL SWZ
139
140%token <integer> INTEGER
141%token <real> REAL
142
143%token AMBIENT ATTENUATION
144%token BACK
145%token CLIP COLOR
146%token DEPTH DIFFUSE DIRECTION
147%token EMISSION ENV EYE
148%token FOG FOGCOORD FRAGMENT FRONT
149%token HALF
150%token INVERSE INVTRANS
151%token LIGHT LIGHTMODEL LIGHTPROD LOCAL
152%token MATERIAL MAT_PROGRAM MATRIX MATRIXINDEX MODELVIEW MVP
153%token NORMAL
154%token OBJECT
155%token PALETTE PARAMS PLANE POINT POINTSIZE POSITION PRIMARY PROGRAM PROJECTION
156%token RANGE RESULT ROW
157%token SCENECOLOR SECONDARY SHININESS SIZE SPECULAR SPOT STATE
158%token TEXCOORD TEXENV TEXGEN TEXGEN_Q TEXGEN_R TEXGEN_S TEXGEN_T TEXTURE TRANSPOSE
159%token TEXTURE_UNIT TEX_1D TEX_2D TEX_3D TEX_CUBE TEX_RECT
Ian Romanick1edd13b2009-07-27 16:24:49 -0700160%token TEX_SHADOW1D TEX_SHADOW2D TEX_SHADOWRECT
Ian Romanickaafd5762009-07-27 17:22:21 -0700161%token TEX_ARRAY1D TEX_ARRAY2D TEX_ARRAYSHADOW1D TEX_ARRAYSHADOW2D
Ian Romanick770cebb2009-07-20 17:44:36 -0700162%token VERTEX VTXATTRIB
163%token WEIGHT
164
165%token <string> IDENTIFIER
166%token <swiz_mask> MASK4 MASK3 MASK2 MASK1 SWIZZLE
167%token DOT_DOT
168%token DOT
169
170%type <inst> instruction ALU_instruction TexInstruction
171%type <inst> ARL_instruction VECTORop_instruction
172%type <inst> SCALARop_instruction BINSCop_instruction BINop_instruction
173%type <inst> TRIop_instruction SWZ_instruction SAMPLE_instruction
174%type <inst> KIL_instruction
175
176%type <dst_reg> dstReg maskedDstReg maskedAddrReg
177%type <src_reg> srcReg scalarSrcReg swizzleSrcReg
178%type <swiz_mask> scalarSuffix swizzleSuffix extendedSwizzle extSwizComp
179%type <swiz_mask> optionalMask
180%type <integer> extSwizSel
181
182%type <sym> progParamArray
183%type <integer> addrRegRelOffset addrRegPosOffset addrRegNegOffset
184%type <src_reg> progParamArrayMem progParamArrayAbs progParamArrayRel
185%type <sym> addrReg
186%type <swiz_mask> addrComponent addrWriteMask
187
188%type <result> resultBinding resultColBinding
189%type <integer> optFaceType optColorType
190%type <integer> optResultFaceType optResultColorType
191
192%type <integer> optTexImageUnitNum texImageUnitNum
193%type <integer> optTexCoordUnitNum texCoordUnitNum
194%type <integer> optLegacyTexUnitNum legacyTexUnitNum
195%type <integer> texImageUnit texTarget
196%type <integer> vtxAttribNum
197
198%type <attrib> attribBinding vtxAttribItem fragAttribItem
199
200%type <temp_sym> paramSingleInit paramSingleItemDecl
201%type <integer> optArraySize
202
203%type <state> stateSingleItem stateMultipleItem
204%type <state> stateMaterialItem
205%type <state> stateLightItem stateLightModelItem stateLightProdItem
206%type <state> stateTexGenItem stateFogItem stateClipPlaneItem statePointItem
207%type <state> stateMatrixItem stateMatrixRow stateMatrixRows
208%type <state> stateTexEnvItem
209
210%type <state> stateLModProperty
211%type <state> stateMatrixName optMatrixRows
212
213%type <integer> stateMatProperty
214%type <integer> stateLightProperty stateSpotProperty
215%type <integer> stateLightNumber stateLProdProperty
216%type <integer> stateTexGenType stateTexGenCoord
217%type <integer> stateTexEnvProperty
218%type <integer> stateFogProperty
219%type <integer> stateClipPlaneNum
220%type <integer> statePointProperty
221
222%type <integer> stateOptMatModifier stateMatModifier stateMatrixRowNum
223%type <integer> stateOptModMatNum stateModMatNum statePaletteMatNum
224%type <integer> stateProgramMatNum
225
226%type <integer> ambDiffSpecProperty
227
228%type <state> programSingleItem progEnvParam progLocalParam
229%type <state> programMultipleItem progEnvParams progLocalParams
230
231%type <temp_sym> paramMultipleInit paramMultInitList paramMultipleItem
232%type <temp_sym> paramSingleItemUse
233
234%type <integer> progEnvParamNum progLocalParamNum
235%type <state> progEnvParamNums progLocalParamNums
236
237%type <vector> paramConstDecl paramConstUse
238%type <vector> paramConstScalarDecl paramConstScalarUse paramConstVector
239%type <real> signedFloatConstant
240%type <negate> optionalSign
241
242%{
243extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
244 void *yyscanner);
245%}
246
247%%
248
249program: language optionSequence statementSequence END
250 ;
251
252language: ARBvp_10
253 {
254 if (state->prog->Target != GL_VERTEX_PROGRAM_ARB) {
255 yyerror(& @1, state, "invalid fragment program header");
256
257 }
258 state->mode = ARB_vertex;
259 }
260 | ARBfp_10
261 {
262 if (state->prog->Target != GL_FRAGMENT_PROGRAM_ARB) {
263 yyerror(& @1, state, "invalid vertex program header");
264 }
265 state->mode = ARB_fragment;
Ian Romanick88018e22009-07-27 15:47:52 -0700266
267 state->option.TexRect =
268 (state->ctx->Extensions.NV_texture_rectangle != GL_FALSE);
Ian Romanick770cebb2009-07-20 17:44:36 -0700269 }
270 ;
271
272optionSequence: optionSequence option
273 |
274 ;
275
276option: OPTION IDENTIFIER ';'
277 {
278 int valid = 0;
279
280 if (state->mode == ARB_vertex) {
281 valid = _mesa_ARBvp_parse_option(state, $2);
282 } else if (state->mode == ARB_fragment) {
283 valid = _mesa_ARBfp_parse_option(state, $2);
284 }
285
286
287 if (!valid) {
Ian Romanick41d56962009-07-27 16:33:16 -0700288 const char *const err_str = (state->mode == ARB_vertex)
289 ? "invalid ARB vertex program option"
290 : "invalid ARB fragment program option";
291
292 yyerror(& @2, state, err_str);
Ian Romanick770cebb2009-07-20 17:44:36 -0700293 YYERROR;
294 }
295 }
296 ;
297
298statementSequence: statementSequence statement
299 |
300 ;
301
302statement: instruction ';'
303 {
304 if ($1 != NULL) {
305 if (state->inst_tail == NULL) {
306 state->inst_head = $1;
307 } else {
308 state->inst_tail->next = $1;
309 }
310
311 state->inst_tail = $1;
312 $1->next = NULL;
313
314 state->prog->NumInstructions++;
315 }
316 }
317 | namingStatement ';'
318 ;
319
320instruction: ALU_instruction
Ian Romanick0db5ef02009-07-22 16:21:54 -0700321 {
322 $$ = $1;
323 state->prog->NumAluInstructions++;
324 }
Ian Romanick770cebb2009-07-20 17:44:36 -0700325 | TexInstruction
Ian Romanick0db5ef02009-07-22 16:21:54 -0700326 {
327 $$ = $1;
328 state->prog->NumTexInstructions++;
329 }
Ian Romanick770cebb2009-07-20 17:44:36 -0700330 ;
331
332ALU_instruction: ARL_instruction
333 | VECTORop_instruction
334 | SCALARop_instruction
335 | BINSCop_instruction
336 | BINop_instruction
337 | TRIop_instruction
338 | SWZ_instruction
339 ;
340
341TexInstruction: SAMPLE_instruction
342 | KIL_instruction
343 ;
344
345ARL_instruction: ARL maskedAddrReg ',' scalarSrcReg
346 {
347 $$ = asm_instruction_ctor(OPCODE_ARL, & $2, & $4, NULL, NULL);
348 }
349 ;
350
351VECTORop_instruction: VECTOR_OP maskedDstReg ',' swizzleSrcReg
352 {
353 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
354 $$->Base.SaturateMode = $1.SaturateMode;
355 }
356 ;
357
358SCALARop_instruction: SCALAR_OP maskedDstReg ',' scalarSrcReg
359 {
360 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
361 $$->Base.SaturateMode = $1.SaturateMode;
362 }
363 ;
364
365BINSCop_instruction: BINSC_OP maskedDstReg ',' scalarSrcReg ',' scalarSrcReg
366 {
367 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
368 $$->Base.SaturateMode = $1.SaturateMode;
369 }
370 ;
371
372
373BINop_instruction: BIN_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg
374 {
375 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
376 $$->Base.SaturateMode = $1.SaturateMode;
377 }
378 ;
379
380TRIop_instruction: TRI_OP maskedDstReg ','
381 swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg
382 {
383 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, & $8);
384 $$->Base.SaturateMode = $1.SaturateMode;
385 }
386 ;
387
388SAMPLE_instruction: SAMPLE_OP maskedDstReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget
389 {
390 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
391 if ($$ != NULL) {
Ian Romanick1edd13b2009-07-27 16:24:49 -0700392 const GLbitfield tex_mask = (1U << $6);
393 GLbitfield shadow_tex = 0;
394 GLbitfield target_mask = 0;
395
396
Ian Romanick770cebb2009-07-20 17:44:36 -0700397 $$->Base.SaturateMode = $1.SaturateMode;
398 $$->Base.TexSrcUnit = $6;
Ian Romanick0db5ef02009-07-22 16:21:54 -0700399
Ian Romanick1edd13b2009-07-27 16:24:49 -0700400 if ($8 < 0) {
401 shadow_tex = tex_mask;
402
403 $$->Base.TexSrcTarget = -$8;
404 $$->Base.TexShadow = 1;
405 } else {
406 $$->Base.TexSrcTarget = $8;
407 }
408
409 target_mask = (1U << $$->Base.TexSrcTarget);
410
411 /* If this texture unit was previously accessed and that access
412 * had a different texture target, generate an error.
413 *
414 * If this texture unit was previously accessed and that access
415 * had a different shadow mode, generate an error.
416 */
417 if ((state->prog->TexturesUsed[$6] != 0)
418 && ((state->prog->TexturesUsed[$6] != target_mask)
419 || ((state->prog->ShadowSamplers & tex_mask)
420 != shadow_tex))) {
421 yyerror(& @8, state,
422 "multiple targets used on one texture image unit");
423 YYERROR;
424 }
425
426
427 state->prog->TexturesUsed[$6] |= target_mask;
428 state->prog->ShadowSamplers |= shadow_tex;
Ian Romanick770cebb2009-07-20 17:44:36 -0700429 }
430 }
431 ;
432
433KIL_instruction: KIL swizzleSrcReg
434 {
435 $$ = asm_instruction_ctor(OPCODE_KIL, NULL, & $2, NULL, NULL);
Ian Romanick0db5ef02009-07-22 16:21:54 -0700436 state->fragment.UsesKill = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700437 }
438 ;
439
440texImageUnit: TEXTURE_UNIT optTexImageUnitNum
441 {
442 $$ = $2;
443 }
444 ;
445
446texTarget: TEX_1D { $$ = TEXTURE_1D_INDEX; }
447 | TEX_2D { $$ = TEXTURE_2D_INDEX; }
448 | TEX_3D { $$ = TEXTURE_3D_INDEX; }
449 | TEX_CUBE { $$ = TEXTURE_CUBE_INDEX; }
450 | TEX_RECT { $$ = TEXTURE_RECT_INDEX; }
Ian Romanick1edd13b2009-07-27 16:24:49 -0700451 | TEX_SHADOW1D { $$ = -TEXTURE_1D_INDEX; }
452 | TEX_SHADOW2D { $$ = -TEXTURE_2D_INDEX; }
453 | TEX_SHADOWRECT { $$ = -TEXTURE_RECT_INDEX; }
Ian Romanickaafd5762009-07-27 17:22:21 -0700454 | TEX_ARRAY1D { $$ = TEXTURE_1D_ARRAY_INDEX; }
455 | TEX_ARRAY2D { $$ = TEXTURE_2D_ARRAY_INDEX; }
456 | TEX_ARRAYSHADOW1D { $$ = -TEXTURE_1D_ARRAY_INDEX; }
457 | TEX_ARRAYSHADOW2D { $$ = -TEXTURE_2D_ARRAY_INDEX; }
Ian Romanick770cebb2009-07-20 17:44:36 -0700458 ;
459
460SWZ_instruction: SWZ maskedDstReg ',' srcReg ',' extendedSwizzle
461 {
462 /* FIXME: Is this correct? Should the extenedSwizzle be applied
463 * FIXME: to the existing swizzle?
464 */
465 $4.Base.Swizzle = $6.swizzle;
466
467 $$ = asm_instruction_ctor(OPCODE_SWZ, & $2, & $4, NULL, NULL);
468 $$->Base.SaturateMode = $1.SaturateMode;
469 }
470 ;
471
472scalarSrcReg: optionalSign srcReg scalarSuffix
473 {
474 $$ = $2;
475
476 if ($1) {
477 $$.Base.Negate = ~$$.Base.Negate;
478 }
479
480 $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
481 $3.swizzle);
482 }
483 ;
484
485swizzleSrcReg: optionalSign srcReg swizzleSuffix
486 {
487 $$ = $2;
488
489 if ($1) {
490 $$.Base.Negate = ~$$.Base.Negate;
491 }
492
493 $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
494 $3.swizzle);
495 }
496 ;
497
498maskedDstReg: dstReg optionalMask
499 {
500 $$ = $1;
501 $$.WriteMask = $2.mask;
502
503 if ($$.File == PROGRAM_OUTPUT) {
504 /* Technically speaking, this should check that it is in
505 * vertex program mode. However, PositionInvariant can never be
506 * set in fragment program mode, so it is somewhat irrelevant.
507 */
508 if (state->option.PositionInvariant
509 && ($$.Index == VERT_RESULT_HPOS)) {
510 yyerror(& @1, state, "position-invariant programs cannot "
511 "write position");
512 YYERROR;
513 }
514
515 state->prog->OutputsWritten |= (1U << $$.Index);
516 }
517 }
518 ;
519
520maskedAddrReg: addrReg addrWriteMask
521 {
522 init_dst_reg(& $$);
523 $$.File = PROGRAM_ADDRESS;
524 $$.Index = 0;
525 $$.WriteMask = $2.mask;
526 }
527 ;
528
529extendedSwizzle: extSwizComp ',' extSwizComp ',' extSwizComp ',' extSwizComp
530 {
531 $$.swizzle = MAKE_SWIZZLE4($1.swizzle, $3.swizzle,
532 $5.swizzle, $7.swizzle);
533 $$.mask = ($1.mask) | ($3.mask << 1) | ($5.mask << 2)
534 | ($7.mask << 3);
535 }
536 ;
537
538extSwizComp: optionalSign extSwizSel
539 {
540 $$.swizzle = $2;
541 $$.mask = ($1) ? 1 : 0;
542 }
543 ;
544
545extSwizSel: INTEGER
546 {
547 if (($1 != 0) && ($1 != 1)) {
548 yyerror(& @1, state, "invalid extended swizzle selector");
549 YYERROR;
550 }
551
552 $$ = ($1 == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
553 }
554 | IDENTIFIER
555 {
556 if (strlen($1) > 1) {
557 yyerror(& @1, state, "invalid extended swizzle selector");
558 YYERROR;
559 }
560
561 switch ($1[0]) {
562 case 'x':
563 $$ = SWIZZLE_X;
564 break;
565 case 'y':
566 $$ = SWIZZLE_Y;
567 break;
568 case 'z':
569 $$ = SWIZZLE_Z;
570 break;
571 case 'w':
572 $$ = SWIZZLE_W;
573 break;
574 default:
575 yyerror(& @1, state, "invalid extended swizzle selector");
576 YYERROR;
577 break;
578 }
579 }
580 ;
581
582srcReg: IDENTIFIER /* temporaryReg | progParamSingle */
583 {
584 struct asm_symbol *const s = (struct asm_symbol *)
585 _mesa_symbol_table_find_symbol(state->st, 0, $1);
586
587 if (s == NULL) {
588 yyerror(& @1, state, "invalid operand variable");
589 YYERROR;
590 } else if ((s->type != at_param) && (s->type != at_temp)
591 && (s->type != at_attrib)) {
592 yyerror(& @1, state, "invalid operand variable");
593 YYERROR;
594 } else if ((s->type == at_param) && s->param_is_array) {
595 yyerror(& @1, state, "non-array access to array PARAM");
596 YYERROR;
597 }
598
599 init_src_reg(& $$);
600 switch (s->type) {
601 case at_temp:
602 $$.Base.File = PROGRAM_TEMPORARY;
603 $$.Base.Index = s->temp_binding;
604 break;
605 case at_param:
606 $$.Base.File = s->param_binding_type;
607 $$.Base.Index = s->param_binding_begin;
608 break;
609 case at_attrib:
610 $$.Base.File = PROGRAM_INPUT;
611 $$.Base.Index = s->attrib_binding;
612 state->prog->InputsRead |= (1U << $$.Base.Index);
613
614 if (!validate_inputs(& @1, state)) {
615 YYERROR;
616 }
617 break;
618
619 default:
620 YYERROR;
621 break;
622 }
623 }
624 | attribBinding
625 {
626 init_src_reg(& $$);
627 $$.Base.File = PROGRAM_INPUT;
628 $$.Base.Index = $1;
629 state->prog->InputsRead |= (1U << $$.Base.Index);
630
631 if (!validate_inputs(& @1, state)) {
632 YYERROR;
633 }
634 }
635 | progParamArray '[' progParamArrayMem ']'
636 {
637 if (! $3.Base.RelAddr
Ian Romanickef80c202009-07-22 17:13:08 -0700638 && ((unsigned) $3.Base.Index >= $1->param_binding_length)) {
Ian Romanick770cebb2009-07-20 17:44:36 -0700639 yyerror(& @3, state, "out of bounds array access");
640 YYERROR;
641 }
642
643 init_src_reg(& $$);
644 $$.Base.File = $1->param_binding_type;
645
646 if ($3.Base.RelAddr) {
647 $1->param_accessed_indirectly = 1;
648
649 $$.Base.RelAddr = 1;
650 $$.Base.Index = $3.Base.Index;
651 $$.Symbol = $1;
652 } else {
653 $$.Base.Index = $1->param_binding_begin + $3.Base.Index;
654 }
655 }
656 | paramSingleItemUse
657 {
658 init_src_reg(& $$);
Ian Romanick69d3d192009-07-22 10:51:18 -0700659 $$.Base.File = ($1.name != NULL)
660 ? $1.param_binding_type
661 : PROGRAM_CONSTANT;
Ian Romanick770cebb2009-07-20 17:44:36 -0700662 $$.Base.Index = $1.param_binding_begin;
663 }
664 ;
665
666dstReg: resultBinding
667 {
668 init_dst_reg(& $$);
669 $$.File = PROGRAM_OUTPUT;
670 $$.Index = $1;
671 }
672 | IDENTIFIER /* temporaryReg | vertexResultReg */
673 {
674 struct asm_symbol *const s = (struct asm_symbol *)
675 _mesa_symbol_table_find_symbol(state->st, 0, $1);
676
677 if (s == NULL) {
678 yyerror(& @1, state, "invalid operand variable");
679 YYERROR;
680 } else if ((s->type != at_output) && (s->type != at_temp)) {
681 yyerror(& @1, state, "invalid operand variable");
682 YYERROR;
683 }
684
685 init_dst_reg(& $$);
686 if (s->type == at_temp) {
687 $$.File = PROGRAM_TEMPORARY;
688 $$.Index = s->temp_binding;
689 } else {
690 $$.File = s->param_binding_type;
691 $$.Index = s->param_binding_begin;
692 }
693 }
694 ;
695
696progParamArray: IDENTIFIER
697 {
698 struct asm_symbol *const s = (struct asm_symbol *)
699 _mesa_symbol_table_find_symbol(state->st, 0, $1);
700
701 if (s == NULL) {
702 yyerror(& @1, state, "invalid operand variable");
703 YYERROR;
704 } else if ((s->type != at_param) || !s->param_is_array) {
705 yyerror(& @1, state, "array access to non-PARAM variable");
706 YYERROR;
707 } else {
708 $$ = s;
709 }
710 }
711 ;
712
713progParamArrayMem: progParamArrayAbs | progParamArrayRel;
714
715progParamArrayAbs: INTEGER
716 {
717 init_src_reg(& $$);
718 $$.Base.Index = $1;
719 }
720 ;
721
722progParamArrayRel: addrReg addrComponent addrRegRelOffset
723 {
724 /* FINISHME: Add support for multiple address registers.
725 */
726 /* FINISHME: Add support for 4-component address registers.
727 */
728 init_src_reg(& $$);
729 $$.Base.RelAddr = 1;
730 $$.Base.Index = $3;
731 }
732 ;
733
734addrRegRelOffset: { $$ = 0; }
735 | '+' addrRegPosOffset { $$ = $2; }
736 | '-' addrRegNegOffset { $$ = -$2; }
737 ;
738
739addrRegPosOffset: INTEGER
740 {
741 if (($1 < 0) || ($1 > 63)) {
742 yyerror(& @1, state,
743 "relative address offset too large (positive)");
744 YYERROR;
745 } else {
746 $$ = $1;
747 }
748 }
749 ;
750
751addrRegNegOffset: INTEGER
752 {
753 if (($1 < 0) || ($1 > 64)) {
754 yyerror(& @1, state,
755 "relative address offset too large (negative)");
756 YYERROR;
757 } else {
758 $$ = $1;
759 }
760 }
761 ;
762
763addrReg: IDENTIFIER
764 {
765 struct asm_symbol *const s = (struct asm_symbol *)
766 _mesa_symbol_table_find_symbol(state->st, 0, $1);
767
768 if (s == NULL) {
769 yyerror(& @1, state, "invalid array member");
770 YYERROR;
771 } else if (s->type != at_address) {
772 yyerror(& @1, state,
773 "invalid variable for indexed array access");
774 YYERROR;
775 } else {
776 $$ = s;
777 }
778 }
779 ;
780
781addrComponent: MASK1
782 {
783 if ($1.mask != WRITEMASK_X) {
784 yyerror(& @1, state, "invalid address component selector");
785 YYERROR;
786 } else {
787 $$ = $1;
788 }
789 }
790 ;
791
792addrWriteMask: MASK1
793 {
794 if ($1.mask != WRITEMASK_X) {
795 yyerror(& @1, state,
796 "address register write mask must be \".x\"");
797 YYERROR;
798 } else {
799 $$ = $1;
800 }
801 }
802 ;
803
804scalarSuffix: MASK1;
805
806swizzleSuffix: MASK1
807 | MASK4
808 | SWIZZLE
809 | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
810 ;
811
812optionalMask: MASK4 | MASK3 | MASK2 | MASK1
813 | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
814 ;
815
816namingStatement: ATTRIB_statement
817 | PARAM_statement
818 | TEMP_statement
819 | ADDRESS_statement
820 | OUTPUT_statement
821 | ALIAS_statement
822 ;
823
824ATTRIB_statement: ATTRIB IDENTIFIER '=' attribBinding
825 {
826 struct asm_symbol *const s =
827 declare_variable(state, $2, at_attrib, & @2);
828
829 if (s == NULL) {
830 YYERROR;
831 } else {
832 s->attrib_binding = $4;
833 state->InputsBound |= (1U << s->attrib_binding);
834
835 if (!validate_inputs(& @4, state)) {
836 YYERROR;
837 }
838 }
839 }
840 ;
841
842attribBinding: VERTEX vtxAttribItem
843 {
844 $$ = $2;
845 }
846 | FRAGMENT fragAttribItem
847 {
848 $$ = $2;
849 }
850 ;
851
852vtxAttribItem: POSITION
853 {
854 $$ = VERT_ATTRIB_POS;
855 }
856 | WEIGHT vtxOptWeightNum
857 {
858 $$ = VERT_ATTRIB_WEIGHT;
859 }
860 | NORMAL
861 {
862 $$ = VERT_ATTRIB_NORMAL;
863 }
864 | COLOR optColorType
865 {
Ian Romanick054ab5a2009-07-27 14:11:38 -0700866 if (!state->ctx->Extensions.EXT_secondary_color) {
867 yyerror(& @2, state, "GL_EXT_secondary_color not supported");
868 YYERROR;
869 }
870
Ian Romanick770cebb2009-07-20 17:44:36 -0700871 $$ = VERT_ATTRIB_COLOR0 + $2;
872 }
873 | FOGCOORD
874 {
Ian Romanick054ab5a2009-07-27 14:11:38 -0700875 if (!state->ctx->Extensions.EXT_fog_coord) {
876 yyerror(& @1, state, "GL_EXT_fog_coord not supported");
877 YYERROR;
878 }
879
Ian Romanick770cebb2009-07-20 17:44:36 -0700880 $$ = VERT_ATTRIB_FOG;
881 }
882 | TEXCOORD optTexCoordUnitNum
883 {
884 $$ = VERT_ATTRIB_TEX0 + $2;
885 }
886 | MATRIXINDEX '[' vtxWeightNum ']'
887 {
Ian Romanick054ab5a2009-07-27 14:11:38 -0700888 yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
Ian Romanick770cebb2009-07-20 17:44:36 -0700889 YYERROR;
890 }
891 | VTXATTRIB '[' vtxAttribNum ']'
892 {
893 $$ = VERT_ATTRIB_GENERIC0 + $3;
894 }
895 ;
896
897vtxAttribNum: INTEGER
898 {
Ian Romanickef80c202009-07-22 17:13:08 -0700899 if ((unsigned) $1 >= state->limits->MaxAttribs) {
Ian Romanick770cebb2009-07-20 17:44:36 -0700900 yyerror(& @1, state, "invalid vertex attribute reference");
901 YYERROR;
902 }
903
904 $$ = $1;
905 }
906 ;
907
908vtxOptWeightNum: | '[' vtxWeightNum ']';
909vtxWeightNum: INTEGER;
910
911fragAttribItem: POSITION
912 {
913 $$ = FRAG_ATTRIB_WPOS;
914 }
915 | COLOR optColorType
916 {
917 $$ = FRAG_ATTRIB_COL0 + $2;
918 }
919 | FOGCOORD
920 {
921 $$ = FRAG_ATTRIB_FOGC;
922 }
923 | TEXCOORD optTexCoordUnitNum
924 {
925 $$ = FRAG_ATTRIB_TEX0 + $2;
926 }
927 ;
928
929PARAM_statement: PARAM_singleStmt | PARAM_multipleStmt;
930
931PARAM_singleStmt: PARAM IDENTIFIER paramSingleInit
932 {
933 struct asm_symbol *const s =
934 declare_variable(state, $2, at_param, & @2);
935
936 if (s == NULL) {
937 YYERROR;
938 } else {
939 s->param_binding_type = $3.param_binding_type;
940 s->param_binding_begin = $3.param_binding_begin;
941 s->param_binding_length = $3.param_binding_length;
942 s->param_is_array = 0;
943 }
944 }
945 ;
946
947PARAM_multipleStmt: PARAM IDENTIFIER '[' optArraySize ']' paramMultipleInit
948 {
Ian Romanickef80c202009-07-22 17:13:08 -0700949 if (($4 != 0) && ((unsigned) $4 != $6.param_binding_length)) {
Ian Romanick770cebb2009-07-20 17:44:36 -0700950 yyerror(& @4, state,
951 "parameter array size and number of bindings must match");
952 YYERROR;
953 } else {
954 struct asm_symbol *const s =
955 declare_variable(state, $2, $6.type, & @2);
956
957 if (s == NULL) {
958 YYERROR;
959 } else {
960 s->param_binding_type = $6.param_binding_type;
961 s->param_binding_begin = $6.param_binding_begin;
962 s->param_binding_length = $6.param_binding_length;
963 s->param_is_array = 1;
964 }
965 }
966 }
967 ;
968
969optArraySize:
970 {
971 $$ = 0;
972 }
973 | INTEGER
974 {
Ian Romanickef80c202009-07-22 17:13:08 -0700975 if (($1 < 1) || ((unsigned) $1 >= state->limits->MaxParameters)) {
Ian Romanick770cebb2009-07-20 17:44:36 -0700976 yyerror(& @1, state, "invalid parameter array size");
977 YYERROR;
978 } else {
979 $$ = $1;
980 }
981 }
982 ;
983
984paramSingleInit: '=' paramSingleItemDecl
985 {
986 $$ = $2;
987 }
988 ;
989
990paramMultipleInit: '=' '{' paramMultInitList '}'
991 {
992 $$ = $3;
993 }
994 ;
995
996paramMultInitList: paramMultipleItem
997 | paramMultInitList ',' paramMultipleItem
998 {
999 $1.param_binding_length += $3.param_binding_length;
1000 $$ = $1;
1001 }
1002 ;
1003
1004paramSingleItemDecl: stateSingleItem
1005 {
1006 memset(& $$, 0, sizeof($$));
1007 $$.param_binding_begin = ~0;
1008 initialize_symbol_from_state(state->prog, & $$, $1);
1009 }
1010 | programSingleItem
1011 {
1012 memset(& $$, 0, sizeof($$));
1013 $$.param_binding_begin = ~0;
1014 initialize_symbol_from_param(state->prog, & $$, $1);
1015 }
1016 | paramConstDecl
1017 {
1018 memset(& $$, 0, sizeof($$));
1019 $$.param_binding_begin = ~0;
1020 initialize_symbol_from_const(state->prog, & $$, & $1);
1021 }
1022 ;
1023
1024paramSingleItemUse: stateSingleItem
1025 {
1026 memset(& $$, 0, sizeof($$));
1027 $$.param_binding_begin = ~0;
1028 initialize_symbol_from_state(state->prog, & $$, $1);
1029 }
1030 | programSingleItem
1031 {
1032 memset(& $$, 0, sizeof($$));
1033 $$.param_binding_begin = ~0;
1034 initialize_symbol_from_param(state->prog, & $$, $1);
1035 }
1036 | paramConstUse
1037 {
1038 memset(& $$, 0, sizeof($$));
1039 $$.param_binding_begin = ~0;
1040 initialize_symbol_from_const(state->prog, & $$, & $1);
1041 }
1042 ;
1043
1044paramMultipleItem: stateMultipleItem
1045 {
1046 memset(& $$, 0, sizeof($$));
1047 $$.param_binding_begin = ~0;
1048 initialize_symbol_from_state(state->prog, & $$, $1);
1049 }
1050 | programMultipleItem
1051 {
1052 memset(& $$, 0, sizeof($$));
1053 $$.param_binding_begin = ~0;
1054 initialize_symbol_from_param(state->prog, & $$, $1);
1055 }
1056 | paramConstDecl
1057 {
1058 memset(& $$, 0, sizeof($$));
1059 $$.param_binding_begin = ~0;
1060 initialize_symbol_from_const(state->prog, & $$, & $1);
1061 }
1062 ;
1063
1064stateMultipleItem: stateSingleItem { memcpy($$, $1, sizeof($$)); }
1065 | STATE stateMatrixRows { memcpy($$, $2, sizeof($$)); }
1066 ;
1067
1068stateSingleItem: STATE stateMaterialItem { memcpy($$, $2, sizeof($$)); }
1069 | STATE stateLightItem { memcpy($$, $2, sizeof($$)); }
1070 | STATE stateLightModelItem { memcpy($$, $2, sizeof($$)); }
1071 | STATE stateLightProdItem { memcpy($$, $2, sizeof($$)); }
1072 | STATE stateTexGenItem { memcpy($$, $2, sizeof($$)); }
1073 | STATE stateTexEnvItem { memcpy($$, $2, sizeof($$)); }
1074 | STATE stateFogItem { memcpy($$, $2, sizeof($$)); }
1075 | STATE stateClipPlaneItem { memcpy($$, $2, sizeof($$)); }
1076 | STATE statePointItem { memcpy($$, $2, sizeof($$)); }
1077 | STATE stateMatrixRow { memcpy($$, $2, sizeof($$)); }
1078 ;
1079
1080stateMaterialItem: MATERIAL optFaceType stateMatProperty
1081 {
1082 memset($$, 0, sizeof($$));
1083 $$[0] = STATE_MATERIAL;
1084 $$[1] = $2;
1085 $$[2] = $3;
1086 }
1087 ;
1088
1089stateMatProperty: ambDiffSpecProperty
1090 {
1091 $$ = $1;
1092 }
1093 | EMISSION
1094 {
1095 $$ = STATE_EMISSION;
1096 }
1097 | SHININESS
1098 {
1099 $$ = STATE_SHININESS;
1100 }
1101 ;
1102
1103stateLightItem: LIGHT '[' stateLightNumber ']' stateLightProperty
1104 {
1105 memset($$, 0, sizeof($$));
1106 $$[0] = STATE_LIGHT;
1107 $$[1] = $3;
1108 $$[2] = $5;
1109 }
1110 ;
1111
1112stateLightProperty: ambDiffSpecProperty
1113 {
1114 $$ = $1;
1115 }
1116 | POSITION
1117 {
1118 $$ = STATE_POSITION;
1119 }
1120 | ATTENUATION
1121 {
Ian Romanick054ab5a2009-07-27 14:11:38 -07001122 if (!state->ctx->Extensions.EXT_point_parameters) {
1123 yyerror(& @1, state, "GL_ARB_point_parameters not supported");
1124 YYERROR;
1125 }
1126
Ian Romanick770cebb2009-07-20 17:44:36 -07001127 $$ = STATE_ATTENUATION;
1128 }
1129 | SPOT stateSpotProperty
1130 {
1131 $$ = $2;
1132 }
1133 | HALF
1134 {
1135 $$ = STATE_HALF_VECTOR;
1136 }
1137 ;
1138
1139stateSpotProperty: DIRECTION
1140 {
1141 $$ = STATE_SPOT_DIRECTION;
1142 }
1143 ;
1144
1145stateLightModelItem: LIGHTMODEL stateLModProperty
1146 {
1147 $$[0] = $2[0];
1148 $$[1] = $2[1];
1149 }
1150 ;
1151
1152stateLModProperty: AMBIENT
1153 {
1154 memset($$, 0, sizeof($$));
1155 $$[0] = STATE_LIGHTMODEL_AMBIENT;
1156 }
1157 | optFaceType SCENECOLOR
1158 {
1159 memset($$, 0, sizeof($$));
1160 $$[0] = STATE_LIGHTMODEL_SCENECOLOR;
1161 $$[1] = $1;
1162 }
1163 ;
1164
1165stateLightProdItem: LIGHTPROD '[' stateLightNumber ']' optFaceType stateLProdProperty
1166 {
1167 memset($$, 0, sizeof($$));
1168 $$[0] = STATE_LIGHTPROD;
1169 $$[1] = $3;
1170 $$[2] = $5;
1171 $$[3] = $6;
1172 }
1173 ;
1174
1175stateLProdProperty: ambDiffSpecProperty;
1176
1177stateTexEnvItem: TEXENV optLegacyTexUnitNum stateTexEnvProperty
1178 {
1179 memset($$, 0, sizeof($$));
1180 $$[0] = $3;
1181 $$[1] = $2;
1182 }
1183 ;
1184
1185stateTexEnvProperty: COLOR
1186 {
1187 $$ = STATE_TEXENV_COLOR;
1188 }
1189 ;
1190
1191ambDiffSpecProperty: AMBIENT
1192 {
1193 $$ = STATE_AMBIENT;
1194 }
1195 | DIFFUSE
1196 {
1197 $$ = STATE_DIFFUSE;
1198 }
1199 | SPECULAR
1200 {
1201 $$ = STATE_SPECULAR;
1202 }
1203 ;
1204
1205stateLightNumber: INTEGER
1206 {
Ian Romanickef80c202009-07-22 17:13:08 -07001207 if ((unsigned) $1 >= state->MaxLights) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001208 yyerror(& @1, state, "invalid light selector");
1209 YYERROR;
1210 }
1211
1212 $$ = $1;
1213 }
1214 ;
1215
1216stateTexGenItem: TEXGEN optTexCoordUnitNum stateTexGenType stateTexGenCoord
1217 {
1218 memset($$, 0, sizeof($$));
1219 $$[0] = STATE_TEXGEN;
1220 $$[1] = $2;
1221 $$[2] = $3 + $4;
1222 }
1223 ;
1224
1225stateTexGenType: EYE
1226 {
1227 $$ = STATE_TEXGEN_EYE_S;
1228 }
1229 | OBJECT
1230 {
1231 $$ = STATE_TEXGEN_OBJECT_S;
1232 }
1233 ;
1234stateTexGenCoord: TEXGEN_S
1235 {
1236 $$ = STATE_TEXGEN_EYE_S - STATE_TEXGEN_EYE_S;
1237 }
1238 | TEXGEN_T
1239 {
1240 $$ = STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S;
1241 }
1242 | TEXGEN_R
1243 {
1244 $$ = STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S;
1245 }
1246 | TEXGEN_Q
1247 {
1248 $$ = STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S;
1249 }
1250 ;
1251
1252stateFogItem: FOG stateFogProperty
1253 {
1254 memset($$, 0, sizeof($$));
1255 $$[0] = $2;
1256 }
1257 ;
1258
1259stateFogProperty: COLOR
1260 {
1261 $$ = STATE_FOG_COLOR;
1262 }
1263 | PARAMS
1264 {
1265 $$ = STATE_FOG_PARAMS;
1266 }
1267 ;
1268
1269stateClipPlaneItem: CLIP '[' stateClipPlaneNum ']' PLANE
1270 {
1271 memset($$, 0, sizeof($$));
1272 $$[0] = STATE_CLIPPLANE;
1273 $$[1] = $3;
1274 }
1275 ;
1276
1277stateClipPlaneNum: INTEGER
1278 {
Ian Romanickef80c202009-07-22 17:13:08 -07001279 if ((unsigned) $1 >= state->MaxClipPlanes) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001280 yyerror(& @1, state, "invalid clip plane selector");
1281 YYERROR;
1282 }
1283
1284 $$ = $1;
1285 }
1286 ;
1287
1288statePointItem: POINT statePointProperty
1289 {
1290 memset($$, 0, sizeof($$));
1291 $$[0] = $2;
1292 }
1293 ;
1294
1295statePointProperty: SIZE
1296 {
1297 $$ = STATE_POINT_SIZE;
1298 }
1299 | ATTENUATION
1300 {
1301 $$ = STATE_POINT_ATTENUATION;
1302 }
1303 ;
1304
1305stateMatrixRow: stateMatrixItem ROW '[' stateMatrixRowNum ']'
1306 {
1307 $$[0] = $1[0];
1308 $$[1] = $1[1];
1309 $$[2] = $4;
1310 $$[3] = $4;
1311 $$[4] = $1[2];
1312 }
1313 ;
1314
1315stateMatrixRows: stateMatrixItem optMatrixRows
1316 {
1317 $$[0] = $1[0];
1318 $$[1] = $1[1];
1319 $$[2] = $2[2];
1320 $$[3] = $2[3];
1321 $$[4] = $1[2];
1322 }
1323 ;
1324
1325optMatrixRows:
1326 {
1327 $$[2] = 0;
1328 $$[3] = 3;
1329 }
1330 | ROW '[' stateMatrixRowNum DOT_DOT stateMatrixRowNum ']'
1331 {
1332 /* It seems logical that the matrix row range specifier would have
1333 * to specify a range or more than one row (i.e., $5 > $3).
1334 * However, the ARB_vertex_program spec says "a program will fail
1335 * to load if <a> is greater than <b>." This means that $3 == $5
1336 * is valid.
1337 */
1338 if ($3 > $5) {
1339 yyerror(& @3, state, "invalid matrix row range");
1340 YYERROR;
1341 }
1342
1343 $$[2] = $3;
1344 $$[3] = $5;
1345 }
1346 ;
1347
1348stateMatrixItem: MATRIX stateMatrixName stateOptMatModifier
1349 {
1350 $$[0] = $2[0];
1351 $$[1] = $2[1];
1352 $$[2] = $3;
1353 }
1354 ;
1355
1356stateOptMatModifier:
1357 {
1358 $$ = 0;
1359 }
1360 | stateMatModifier
1361 {
1362 $$ = $1;
1363 }
1364 ;
1365
1366stateMatModifier: INVERSE
1367 {
1368 $$ = STATE_MATRIX_INVERSE;
1369 }
1370 | TRANSPOSE
1371 {
1372 $$ = STATE_MATRIX_TRANSPOSE;
1373 }
1374 | INVTRANS
1375 {
1376 $$ = STATE_MATRIX_INVTRANS;
1377 }
1378 ;
1379
1380stateMatrixRowNum: INTEGER
1381 {
1382 if ($1 > 3) {
1383 yyerror(& @1, state, "invalid matrix row reference");
1384 YYERROR;
1385 }
1386
1387 $$ = $1;
1388 }
1389 ;
1390
1391stateMatrixName: MODELVIEW stateOptModMatNum
1392 {
1393 $$[0] = STATE_MODELVIEW_MATRIX;
1394 $$[1] = $2;
1395 }
1396 | PROJECTION
1397 {
1398 $$[0] = STATE_PROJECTION_MATRIX;
1399 $$[1] = 0;
1400 }
1401 | MVP
1402 {
1403 $$[0] = STATE_MVP_MATRIX;
1404 $$[1] = 0;
1405 }
1406 | TEXTURE optTexCoordUnitNum
1407 {
1408 $$[0] = STATE_TEXTURE_MATRIX;
1409 $$[1] = $2;
1410 }
1411 | PALETTE '[' statePaletteMatNum ']'
1412 {
Ian Romanick054ab5a2009-07-27 14:11:38 -07001413 yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
Ian Romanick770cebb2009-07-20 17:44:36 -07001414 YYERROR;
1415 }
1416 | MAT_PROGRAM '[' stateProgramMatNum ']'
1417 {
1418 $$[0] = STATE_PROGRAM_MATRIX;
1419 $$[1] = $3;
1420 }
1421 ;
1422
1423stateOptModMatNum:
1424 {
1425 $$ = 0;
1426 }
1427 | stateModMatNum
1428 {
1429 $$ = $1;
1430 }
1431 ;
1432stateModMatNum: INTEGER
1433 {
1434 /* Since GL_ARB_vertex_blend isn't supported, only modelview matrix
1435 * zero is valid.
1436 */
1437 if ($1 != 0) {
1438 yyerror(& @1, state, "invalid modelview matrix index");
1439 YYERROR;
1440 }
1441
1442 $$ = $1;
1443 }
1444 ;
1445statePaletteMatNum: INTEGER
1446 {
1447 /* Since GL_ARB_matrix_palette isn't supported, just let any value
1448 * through here. The error will be generated later.
1449 */
1450 $$ = $1;
1451 }
1452 ;
1453stateProgramMatNum: INTEGER
1454 {
Ian Romanickef80c202009-07-22 17:13:08 -07001455 if ((unsigned) $1 >= state->MaxProgramMatrices) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001456 yyerror(& @1, state, "invalid program matrix selector");
1457 YYERROR;
1458 }
1459
1460 $$ = $1;
1461 }
1462 ;
1463
1464
1465
1466programSingleItem: progEnvParam | progLocalParam;
1467
1468programMultipleItem: progEnvParams | progLocalParams;
1469
1470progEnvParams: PROGRAM ENV '[' progEnvParamNums ']'
1471 {
1472 memset($$, 0, sizeof($$));
1473 $$[0] = state->state_param_enum;
1474 $$[1] = STATE_ENV;
1475 $$[2] = $4[0];
1476 $$[3] = $4[1];
1477 }
1478 ;
1479
1480progEnvParamNums: progEnvParamNum
1481 {
1482 $$[0] = $1;
1483 $$[1] = $1;
1484 }
1485 | progEnvParamNum DOT_DOT progEnvParamNum
1486 {
1487 $$[0] = $1;
1488 $$[1] = $3;
1489 }
1490 ;
1491
1492progEnvParam: PROGRAM ENV '[' progEnvParamNum ']'
1493 {
1494 memset($$, 0, sizeof($$));
1495 $$[0] = state->state_param_enum;
1496 $$[1] = STATE_ENV;
1497 $$[2] = $4;
1498 $$[3] = $4;
1499 }
1500 ;
1501
1502progLocalParams: PROGRAM LOCAL '[' progLocalParamNums ']'
1503 {
1504 memset($$, 0, sizeof($$));
1505 $$[0] = state->state_param_enum;
1506 $$[1] = STATE_LOCAL;
1507 $$[2] = $4[0];
1508 $$[3] = $4[1];
1509 }
1510
1511progLocalParamNums: progLocalParamNum
1512 {
1513 $$[0] = $1;
1514 $$[1] = $1;
1515 }
1516 | progLocalParamNum DOT_DOT progLocalParamNum
1517 {
1518 $$[0] = $1;
1519 $$[1] = $3;
1520 }
1521 ;
1522
1523progLocalParam: PROGRAM LOCAL '[' progLocalParamNum ']'
1524 {
1525 memset($$, 0, sizeof($$));
1526 $$[0] = state->state_param_enum;
1527 $$[1] = STATE_LOCAL;
1528 $$[2] = $4;
1529 $$[3] = $4;
1530 }
1531 ;
1532
1533progEnvParamNum: INTEGER
1534 {
Ian Romanickef80c202009-07-22 17:13:08 -07001535 if ((unsigned) $1 >= state->limits->MaxEnvParams) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001536 yyerror(& @1, state, "invalid environment parameter reference");
1537 YYERROR;
1538 }
1539 $$ = $1;
1540 }
1541 ;
1542
1543progLocalParamNum: INTEGER
1544 {
Ian Romanickef80c202009-07-22 17:13:08 -07001545 if ((unsigned) $1 >= state->limits->MaxLocalParams) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001546 yyerror(& @1, state, "invalid local parameter reference");
1547 YYERROR;
1548 }
1549 $$ = $1;
1550 }
1551 ;
1552
1553
1554
1555paramConstDecl: paramConstScalarDecl | paramConstVector;
1556paramConstUse: paramConstScalarUse | paramConstVector;
1557
1558paramConstScalarDecl: signedFloatConstant
1559 {
1560 $$.count = 1;
1561 $$.data[0] = $1;
1562 }
1563 ;
1564
1565paramConstScalarUse: REAL
1566 {
1567 $$.count = 1;
1568 $$.data[0] = $1;
1569 }
1570 | INTEGER
1571 {
1572 $$.count = 1;
1573 $$.data[0] = (float) $1;
1574 }
1575 ;
1576
1577paramConstVector: '{' signedFloatConstant '}'
1578 {
1579 $$.count = 1;
1580 $$.data[0] = $2;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001581 $$.data[1] = 0.0f;
1582 $$.data[2] = 0.0f;
1583 $$.data[3] = 0.0f;
Ian Romanick770cebb2009-07-20 17:44:36 -07001584 }
1585 | '{' signedFloatConstant ',' signedFloatConstant '}'
1586 {
1587 $$.count = 2;
1588 $$.data[0] = $2;
1589 $$.data[1] = $4;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001590 $$.data[2] = 0.0f;
1591 $$.data[3] = 0.0f;
Ian Romanick770cebb2009-07-20 17:44:36 -07001592 }
1593 | '{' signedFloatConstant ',' signedFloatConstant ','
1594 signedFloatConstant '}'
1595 {
1596 $$.count = 3;
1597 $$.data[0] = $2;
1598 $$.data[1] = $4;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001599 $$.data[2] = $6;
1600 $$.data[3] = 0.0f;
Ian Romanick770cebb2009-07-20 17:44:36 -07001601 }
1602 | '{' signedFloatConstant ',' signedFloatConstant ','
1603 signedFloatConstant ',' signedFloatConstant '}'
1604 {
1605 $$.count = 4;
1606 $$.data[0] = $2;
1607 $$.data[1] = $4;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001608 $$.data[2] = $6;
1609 $$.data[3] = $8;
Ian Romanick770cebb2009-07-20 17:44:36 -07001610 }
1611 ;
1612
1613signedFloatConstant: optionalSign REAL
1614 {
1615 $$ = ($1) ? -$2 : $2;
1616 }
1617 | optionalSign INTEGER
1618 {
1619 $$ = (float)(($1) ? -$2 : $2);
1620 }
1621 ;
1622
1623optionalSign: '+' { $$ = FALSE; }
1624 | '-' { $$ = TRUE; }
1625 | { $$ = FALSE; }
1626 ;
1627
1628TEMP_statement: TEMP { $<integer>$ = $1; } varNameList
1629 ;
1630
1631ADDRESS_statement: ADDRESS { $<integer>$ = $1; } varNameList
1632 ;
1633
1634varNameList: varNameList ',' IDENTIFIER
1635 {
1636 if (!declare_variable(state, $3, $<integer>0, & @3)) {
1637 YYERROR;
1638 }
1639 }
1640 | IDENTIFIER
1641 {
1642 if (!declare_variable(state, $1, $<integer>0, & @1)) {
1643 YYERROR;
1644 }
1645 }
1646 ;
1647
1648OUTPUT_statement: OUTPUT IDENTIFIER '=' resultBinding
1649 {
1650 struct asm_symbol *const s =
1651 declare_variable(state, $2, at_output, & @2);
1652
1653 if (s == NULL) {
1654 YYERROR;
1655 } else {
1656 s->output_binding = $4;
1657 }
1658 }
1659 ;
1660
1661resultBinding: RESULT POSITION
1662 {
1663 if (state->mode == ARB_vertex) {
1664 $$ = VERT_RESULT_HPOS;
1665 } else {
1666 yyerror(& @2, state, "invalid program result name");
1667 YYERROR;
1668 }
1669 }
1670 | RESULT FOGCOORD
1671 {
1672 if (state->mode == ARB_vertex) {
1673 $$ = VERT_RESULT_FOGC;
1674 } else {
1675 yyerror(& @2, state, "invalid program result name");
1676 YYERROR;
1677 }
1678 }
1679 | RESULT resultColBinding
1680 {
1681 $$ = $2;
1682 }
1683 | RESULT POINTSIZE
1684 {
1685 if (state->mode == ARB_vertex) {
1686 $$ = VERT_RESULT_PSIZ;
1687 } else {
1688 yyerror(& @2, state, "invalid program result name");
1689 YYERROR;
1690 }
1691 }
1692 | RESULT TEXCOORD optTexCoordUnitNum
1693 {
1694 if (state->mode == ARB_vertex) {
1695 $$ = VERT_RESULT_TEX0 + $3;
1696 } else {
1697 yyerror(& @2, state, "invalid program result name");
1698 YYERROR;
1699 }
1700 }
1701 | RESULT DEPTH
1702 {
1703 if (state->mode == ARB_fragment) {
1704 $$ = FRAG_RESULT_DEPTH;
1705 } else {
1706 yyerror(& @2, state, "invalid program result name");
1707 YYERROR;
1708 }
1709 }
1710 ;
1711
1712resultColBinding: COLOR optResultFaceType optResultColorType
1713 {
1714 $$ = $2 + $3;
1715 }
1716 ;
1717
1718optResultFaceType:
1719 {
1720 $$ = (state->mode == ARB_vertex)
1721 ? VERT_RESULT_COL0
1722 : FRAG_RESULT_COLOR;
1723 }
1724 | FRONT
1725 {
1726 if (state->mode == ARB_vertex) {
1727 $$ = VERT_RESULT_COL0;
1728 } else {
1729 yyerror(& @1, state, "invalid program result name");
1730 YYERROR;
1731 }
1732 }
1733 | BACK
1734 {
1735 if (state->mode == ARB_vertex) {
1736 $$ = VERT_RESULT_BFC0;
1737 } else {
1738 yyerror(& @1, state, "invalid program result name");
1739 YYERROR;
1740 }
1741 }
1742 ;
1743
1744optResultColorType:
1745 {
1746 $$ = 0;
1747 }
1748 | PRIMARY
1749 {
1750 if (state->mode == ARB_vertex) {
1751 $$ = 0;
1752 } else {
1753 yyerror(& @1, state, "invalid program result name");
1754 YYERROR;
1755 }
1756 }
1757 | SECONDARY
1758 {
1759 if (state->mode == ARB_vertex) {
1760 $$ = 1;
1761 } else {
1762 yyerror(& @1, state, "invalid program result name");
1763 YYERROR;
1764 }
1765 }
1766 ;
1767
1768optFaceType: { $$ = 0; }
1769 | FRONT { $$ = 0; }
1770 | BACK { $$ = 1; }
1771 ;
1772
1773optColorType: { $$ = 0; }
1774 | PRIMARY { $$ = 0; }
1775 | SECONDARY { $$ = 1; }
1776 ;
1777
1778optTexCoordUnitNum: { $$ = 0; }
1779 | '[' texCoordUnitNum ']' { $$ = $2; }
1780 ;
1781
1782optTexImageUnitNum: { $$ = 0; }
1783 | '[' texImageUnitNum ']' { $$ = $2; }
1784 ;
1785
1786optLegacyTexUnitNum: { $$ = 0; }
1787 | '[' legacyTexUnitNum ']' { $$ = $2; }
1788 ;
1789
1790texCoordUnitNum: INTEGER
1791 {
Ian Romanickef80c202009-07-22 17:13:08 -07001792 if ((unsigned) $1 >= state->MaxTextureCoordUnits) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001793 yyerror(& @1, state, "invalid texture coordinate unit selector");
1794 YYERROR;
1795 }
1796
1797 $$ = $1;
1798 }
1799 ;
1800
1801texImageUnitNum: INTEGER
1802 {
Ian Romanickef80c202009-07-22 17:13:08 -07001803 if ((unsigned) $1 >= state->MaxTextureImageUnits) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001804 yyerror(& @1, state, "invalid texture image unit selector");
1805 YYERROR;
1806 }
1807
1808 $$ = $1;
1809 }
1810 ;
1811
1812legacyTexUnitNum: INTEGER
1813 {
Ian Romanickef80c202009-07-22 17:13:08 -07001814 if ((unsigned) $1 >= state->MaxTextureUnits) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001815 yyerror(& @1, state, "invalid texture unit selector");
1816 YYERROR;
1817 }
1818
1819 $$ = $1;
1820 }
1821 ;
1822
1823ALIAS_statement: ALIAS IDENTIFIER '=' IDENTIFIER
1824 {
1825 struct asm_symbol *exist = (struct asm_symbol *)
1826 _mesa_symbol_table_find_symbol(state->st, 0, $2);
1827 struct asm_symbol *target = (struct asm_symbol *)
1828 _mesa_symbol_table_find_symbol(state->st, 0, $4);
1829
1830
1831 if (exist != NULL) {
1832 yyerror(& @2, state, "redeclared identifier");
1833 YYERROR;
1834 } else if (target == NULL) {
1835 yyerror(& @4, state,
1836 "undefined variable binding in ALIAS statement");
1837 YYERROR;
1838 } else {
1839 _mesa_symbol_table_add_symbol(state->st, 0, $2, target);
1840 }
1841 }
1842 ;
1843
1844%%
1845
1846struct asm_instruction *
1847asm_instruction_ctor(gl_inst_opcode op,
1848 const struct prog_dst_register *dst,
1849 const struct asm_src_register *src0,
1850 const struct asm_src_register *src1,
1851 const struct asm_src_register *src2)
1852{
1853 struct asm_instruction *inst = calloc(1, sizeof(struct asm_instruction));
1854
1855 if (inst) {
Ian Romanickef80c202009-07-22 17:13:08 -07001856 _mesa_init_instructions(& inst->Base, 1);
Ian Romanick770cebb2009-07-20 17:44:36 -07001857 inst->Base.Opcode = op;
1858 inst->Base.DstReg = *dst;
1859
1860 inst->Base.SrcReg[0] = src0->Base;
1861 inst->SrcReg[0] = *src0;
1862
1863 if (src1 != NULL) {
1864 inst->Base.SrcReg[1] = src1->Base;
1865 inst->SrcReg[1] = *src1;
Ian Romanickaec42912009-07-22 12:29:48 -07001866 } else {
1867 init_src_reg(& inst->SrcReg[1]);
Ian Romanick770cebb2009-07-20 17:44:36 -07001868 }
1869
1870 if (src2 != NULL) {
1871 inst->Base.SrcReg[2] = src2->Base;
1872 inst->SrcReg[2] = *src2;
Ian Romanickaec42912009-07-22 12:29:48 -07001873 } else {
1874 init_src_reg(& inst->SrcReg[2]);
Ian Romanick770cebb2009-07-20 17:44:36 -07001875 }
1876 }
1877
1878 return inst;
1879}
1880
1881
1882void
1883init_dst_reg(struct prog_dst_register *r)
1884{
1885 memset(r, 0, sizeof(*r));
1886 r->File = PROGRAM_UNDEFINED;
1887 r->WriteMask = WRITEMASK_XYZW;
1888 r->CondMask = COND_TR;
1889 r->CondSwizzle = SWIZZLE_NOOP;
1890}
1891
1892
1893void
1894init_src_reg(struct asm_src_register *r)
1895{
1896 memset(r, 0, sizeof(*r));
1897 r->Base.File = PROGRAM_UNDEFINED;
1898 r->Base.Swizzle = SWIZZLE_NOOP;
1899 r->Symbol = NULL;
1900}
1901
1902
1903/**
1904 * Validate the set of inputs used by a program
1905 *
1906 * Validates that legal sets of inputs are used by the program. In this case
1907 * "used" included both reading the input or binding the input to a name using
1908 * the \c ATTRIB command.
1909 *
1910 * \return
1911 * \c TRUE if the combination of inputs used is valid, \c FALSE otherwise.
1912 */
1913int
1914validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
1915{
1916 const int inputs = state->prog->InputsRead | state->InputsBound;
1917
1918 if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
1919 yyerror(locp, state, "illegal use of generic attribute and name attribute");
1920 return 0;
1921 }
1922
1923 return 1;
1924}
1925
1926
1927struct asm_symbol *
1928declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
1929 struct YYLTYPE *locp)
1930{
1931 struct asm_symbol *s = NULL;
1932 struct asm_symbol *exist = (struct asm_symbol *)
1933 _mesa_symbol_table_find_symbol(state->st, 0, name);
1934
1935
1936 if (exist != NULL) {
1937 yyerror(locp, state, "redeclared identifier");
1938 } else {
1939 s = calloc(1, sizeof(struct asm_symbol));
1940 s->name = name;
1941 s->type = t;
1942
1943 switch (t) {
1944 case at_temp:
1945 if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
1946 yyerror(locp, state, "too many temporaries declared");
1947 free(s);
1948 return NULL;
1949 }
1950
1951 s->temp_binding = state->prog->NumTemporaries;
1952 state->prog->NumTemporaries++;
1953 break;
1954
1955 case at_address:
1956 if (state->prog->NumAddressRegs >= state->limits->MaxAddressRegs) {
1957 yyerror(locp, state, "too many address registers declared");
1958 free(s);
1959 return NULL;
1960 }
1961
1962 /* FINISHME: Add support for multiple address registers.
1963 */
1964 state->prog->NumAddressRegs++;
1965 break;
1966
1967 default:
1968 break;
1969 }
1970
1971 _mesa_symbol_table_add_symbol(state->st, 0, s->name, s);
Ian Romanick94b45562009-07-27 12:21:26 -07001972 s->next = state->sym;
1973 state->sym = s;
Ian Romanick770cebb2009-07-20 17:44:36 -07001974 }
1975
1976 return s;
1977}
1978
1979
1980int add_state_reference(struct gl_program_parameter_list *param_list,
1981 const gl_state_index tokens[STATE_LENGTH])
1982{
1983 const GLuint size = 4; /* XXX fix */
1984 char *name;
1985 GLint index;
1986
1987 name = _mesa_program_state_string(tokens);
1988 index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
1989 size, GL_NONE,
1990 NULL, (gl_state_index *) tokens, 0x0);
1991 param_list->StateFlags |= _mesa_program_state_flags(tokens);
1992
1993 /* free name string here since we duplicated it in add_parameter() */
1994 _mesa_free(name);
1995
1996 return index;
1997}
1998
1999
2000int
2001initialize_symbol_from_state(struct gl_program *prog,
2002 struct asm_symbol *param_var,
2003 const gl_state_index tokens[STATE_LENGTH])
2004{
2005 int idx = -1;
2006 gl_state_index state_tokens[STATE_LENGTH];
2007
2008
2009 memcpy(state_tokens, tokens, sizeof(state_tokens));
2010
2011 param_var->type = at_param;
Ian Romanick28b13032009-07-22 16:03:32 -07002012 param_var->param_binding_type = PROGRAM_STATE_VAR;
Ian Romanick770cebb2009-07-20 17:44:36 -07002013
2014 /* If we are adding a STATE_MATRIX that has multiple rows, we need to
2015 * unroll it and call add_state_reference() for each row
2016 */
2017 if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
2018 state_tokens[0] == STATE_PROJECTION_MATRIX ||
2019 state_tokens[0] == STATE_MVP_MATRIX ||
2020 state_tokens[0] == STATE_TEXTURE_MATRIX ||
2021 state_tokens[0] == STATE_PROGRAM_MATRIX)
2022 && (state_tokens[2] != state_tokens[3])) {
2023 int row;
2024 const int first_row = state_tokens[2];
2025 const int last_row = state_tokens[3];
2026
2027 for (row = first_row; row <= last_row; row++) {
2028 state_tokens[2] = state_tokens[3] = row;
2029
2030 idx = add_state_reference(prog->Parameters, state_tokens);
2031 if (param_var->param_binding_begin == ~0U)
2032 param_var->param_binding_begin = idx;
2033 param_var->param_binding_length++;
2034 }
2035 }
2036 else {
2037 idx = add_state_reference(prog->Parameters, state_tokens);
2038 if (param_var->param_binding_begin == ~0U)
2039 param_var->param_binding_begin = idx;
2040 param_var->param_binding_length++;
2041 }
2042
2043 return idx;
2044}
2045
2046
2047int
2048initialize_symbol_from_param(struct gl_program *prog,
2049 struct asm_symbol *param_var,
2050 const gl_state_index tokens[STATE_LENGTH])
2051{
2052 int idx = -1;
2053 gl_state_index state_tokens[STATE_LENGTH];
2054
2055
2056 memcpy(state_tokens, tokens, sizeof(state_tokens));
2057
2058 assert((state_tokens[0] == STATE_VERTEX_PROGRAM)
2059 || (state_tokens[0] == STATE_FRAGMENT_PROGRAM));
2060 assert((state_tokens[1] == STATE_ENV)
2061 || (state_tokens[1] == STATE_LOCAL));
2062
2063 param_var->type = at_param;
Ian Romanick28b13032009-07-22 16:03:32 -07002064 param_var->param_binding_type = (state_tokens[1] == STATE_ENV)
2065 ? PROGRAM_ENV_PARAM : PROGRAM_LOCAL_PARAM;
Ian Romanick770cebb2009-07-20 17:44:36 -07002066
2067 /* If we are adding a STATE_ENV or STATE_LOCAL that has multiple elements,
2068 * we need to unroll it and call add_state_reference() for each row
2069 */
2070 if (state_tokens[2] != state_tokens[3]) {
2071 int row;
2072 const int first_row = state_tokens[2];
2073 const int last_row = state_tokens[3];
2074
2075 for (row = first_row; row <= last_row; row++) {
2076 state_tokens[2] = state_tokens[3] = row;
2077
2078 idx = add_state_reference(prog->Parameters, state_tokens);
2079 if (param_var->param_binding_begin == ~0U)
2080 param_var->param_binding_begin = idx;
2081 param_var->param_binding_length++;
2082 }
2083 }
2084 else {
2085 idx = add_state_reference(prog->Parameters, state_tokens);
2086 if (param_var->param_binding_begin == ~0U)
2087 param_var->param_binding_begin = idx;
2088 param_var->param_binding_length++;
2089 }
2090
2091 return idx;
2092}
2093
2094
2095int
2096initialize_symbol_from_const(struct gl_program *prog,
2097 struct asm_symbol *param_var,
2098 const struct asm_vector *vec)
2099{
2100 const int idx = _mesa_add_parameter(prog->Parameters, PROGRAM_CONSTANT,
2101 NULL, vec->count, GL_NONE, vec->data,
2102 NULL, 0x0);
2103
2104 param_var->type = at_param;
Ian Romanick28b13032009-07-22 16:03:32 -07002105 param_var->param_binding_type = PROGRAM_CONSTANT;
Ian Romanick770cebb2009-07-20 17:44:36 -07002106
2107 if (param_var->param_binding_begin == ~0U)
2108 param_var->param_binding_begin = idx;
2109 param_var->param_binding_length++;
2110
2111 return idx;
2112}
2113
2114
Ian Romanick44843c72009-07-22 15:06:49 -07002115char *
2116make_error_string(const char *fmt, ...)
2117{
2118 int length;
2119 char *str;
2120 va_list args;
2121
2122 va_start(args, fmt);
2123
2124 /* Call vsnprintf once to determine how large the final string is. Call it
2125 * again to do the actual formatting. from the vsnprintf manual page:
2126 *
2127 * Upon successful return, these functions return the number of
2128 * characters printed (not including the trailing '\0' used to end
2129 * output to strings).
2130 */
2131 length = 1 + vsnprintf(NULL, 0, fmt, args);
2132
2133 str = _mesa_malloc(length);
2134 if (str) {
2135 vsnprintf(str, length, fmt, args);
2136 }
2137
2138 va_end(args);
2139
2140 return str;
2141}
2142
2143
Ian Romanick770cebb2009-07-20 17:44:36 -07002144void
2145yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
2146{
Ian Romanick44843c72009-07-22 15:06:49 -07002147 char *err_str;
Ian Romanick770cebb2009-07-20 17:44:36 -07002148
Ian Romanick44843c72009-07-22 15:06:49 -07002149
2150 err_str = make_error_string("glProgramStringARB(%s)\n", s);
2151 if (err_str) {
2152 _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
2153 _mesa_free(err_str);
2154 }
2155
2156 err_str = make_error_string("line %u, char %u: error: %s\n",
2157 locp->first_line, locp->first_column, s);
2158 _mesa_set_program_error(state->ctx, locp->position, err_str);
2159
2160 if (err_str) {
2161 _mesa_free(err_str);
2162 }
Ian Romanick770cebb2009-07-20 17:44:36 -07002163}
2164
Ian Romanick44843c72009-07-22 15:06:49 -07002165
Ian Romanick770cebb2009-07-20 17:44:36 -07002166GLboolean
2167_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
2168 GLsizei len, struct asm_parser_state *state)
2169{
2170 struct gl_program_constants limits;
2171 struct asm_instruction *inst;
2172 unsigned i;
2173 GLubyte *strz;
Ian Romanick94b45562009-07-27 12:21:26 -07002174 GLboolean result = GL_FALSE;
2175 void *temp;
2176 struct asm_symbol *sym;
Ian Romanick770cebb2009-07-20 17:44:36 -07002177
Ian Romanick44843c72009-07-22 15:06:49 -07002178 state->ctx = ctx;
Ian Romanick770cebb2009-07-20 17:44:36 -07002179 state->prog->Target = target;
2180 state->prog->Parameters = _mesa_new_parameter_list();
2181
2182 /* Make a copy of the program string and force it to be NUL-terminated.
2183 */
2184 strz = (GLubyte *) _mesa_malloc(len + 1);
2185 if (strz == NULL) {
2186 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
2187 return GL_FALSE;
2188 }
2189 _mesa_memcpy (strz, str, len);
2190 strz[len] = '\0';
2191
2192 state->prog->String = strz;
2193
2194 state->st = _mesa_symbol_table_ctor();
2195
2196 /* All of these limits should come from ctx.
2197 */
2198 limits.MaxInstructions = 128;
2199 limits.MaxAluInstructions = 128;
2200 limits.MaxTexInstructions = 128;
2201 limits.MaxTexIndirections = 128;
2202 limits.MaxAttribs = 16;
2203 limits.MaxTemps = 128;
2204 limits.MaxAddressRegs = 1;
2205 limits.MaxParameters = 128;
2206 limits.MaxLocalParams = 256;
2207 limits.MaxEnvParams = 128;
2208 limits.MaxNativeInstructions = 128;
2209 limits.MaxNativeAluInstructions = 128;
2210 limits.MaxNativeTexInstructions = 128;
2211 limits.MaxNativeTexIndirections = 128;
2212 limits.MaxNativeAttribs = 16;
2213 limits.MaxNativeTemps = 128;
2214 limits.MaxNativeAddressRegs = 1;
2215 limits.MaxNativeParameters = 128;
2216 limits.MaxUniformComponents = 0;
2217
2218 state->limits = & limits;
2219
2220 state->MaxTextureImageUnits = 16;
2221 state->MaxTextureCoordUnits = 8;
2222 state->MaxTextureUnits = 8;
2223 state->MaxClipPlanes = 6;
2224 state->MaxLights = 8;
2225 state->MaxProgramMatrices = 8;
2226
2227 state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
2228 ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
2229
2230 _mesa_set_program_error(ctx, -1, NULL);
2231
2232 _mesa_program_lexer_ctor(& state->scanner, state, (const char *) str, len);
2233 yyparse(state);
2234 _mesa_program_lexer_dtor(state->scanner);
2235
2236
Ian Romanick44843c72009-07-22 15:06:49 -07002237 if (ctx->Program.ErrorPos != -1) {
Ian Romanick94b45562009-07-27 12:21:26 -07002238 goto error;
Ian Romanick44843c72009-07-22 15:06:49 -07002239 }
2240
Ian Romanick770cebb2009-07-20 17:44:36 -07002241 if (! _mesa_layout_parameters(state)) {
Ian Romanick44843c72009-07-22 15:06:49 -07002242 struct YYLTYPE loc;
2243
2244 loc.first_line = 0;
2245 loc.first_column = 0;
2246 loc.position = len;
2247
2248 yyerror(& loc, state, "invalid PARAM usage");
Ian Romanick94b45562009-07-27 12:21:26 -07002249 goto error;
Ian Romanick770cebb2009-07-20 17:44:36 -07002250 }
2251
2252
2253
2254 /* Add one instruction to store the "END" instruction.
2255 */
2256 state->prog->Instructions =
2257 _mesa_alloc_instructions(state->prog->NumInstructions + 1);
2258 inst = state->inst_head;
2259 for (i = 0; i < state->prog->NumInstructions; i++) {
2260 struct asm_instruction *const temp = inst->next;
2261
2262 state->prog->Instructions[i] = inst->Base;
Ian Romanick770cebb2009-07-20 17:44:36 -07002263 inst = temp;
2264 }
2265
2266 /* Finally, tag on an OPCODE_END instruction */
2267 {
2268 const GLuint numInst = state->prog->NumInstructions;
2269 _mesa_init_instructions(state->prog->Instructions + numInst, 1);
2270 state->prog->Instructions[numInst].Opcode = OPCODE_END;
2271 }
2272 state->prog->NumInstructions++;
2273
Ian Romanickc2ee82d2009-07-22 15:27:31 -07002274 state->prog->NumParameters = state->prog->Parameters->NumParameters;
2275
Ian Romanick770cebb2009-07-20 17:44:36 -07002276 /*
2277 * Initialize native counts to logical counts. The device driver may
2278 * change them if program is translated into a hardware program.
2279 */
2280 state->prog->NumNativeInstructions = state->prog->NumInstructions;
2281 state->prog->NumNativeTemporaries = state->prog->NumTemporaries;
2282 state->prog->NumNativeParameters = state->prog->NumParameters;
2283 state->prog->NumNativeAttributes = state->prog->NumAttributes;
2284 state->prog->NumNativeAddressRegs = state->prog->NumAddressRegs;
2285
Ian Romanick94b45562009-07-27 12:21:26 -07002286 result = GL_TRUE;
2287
2288error:
2289 for (inst = state->inst_head; inst != NULL; inst = temp) {
2290 temp = inst->next;
2291 _mesa_free(inst);
2292 }
2293
2294 state->inst_head = NULL;
2295 state->inst_tail = NULL;
2296
2297 for (sym = state->sym; sym != NULL; sym = temp) {
2298 temp = sym->next;
2299
2300 _mesa_free((void *) sym->name);
2301 _mesa_free(sym);
2302 }
2303 state->sym = NULL;
2304
2305 _mesa_symbol_table_dtor(state->st);
2306 state->st = NULL;
2307
2308 return result;
Ian Romanick770cebb2009-07-20 17:44:36 -07002309}