blob: fa94f763c4d6cbec7c319a051715a44ea2663361 [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;
Ian Romanick565a2a82009-07-30 10:51:43 -0700124
125 struct {
126 unsigned swz;
127 unsigned rgba_valid:1;
128 unsigned xyzw_valid:1;
129 unsigned negate:1;
130 } ext_swizzle;
Ian Romanick770cebb2009-07-20 17:44:36 -0700131}
132
133%token ARBvp_10 ARBfp_10
134
135/* Tokens for assembler pseudo-ops */
136%token <integer> ADDRESS
137%token ALIAS ATTRIB
138%token OPTION OUTPUT
139%token PARAM
140%token <integer> TEMP
141%token END
142
143 /* Tokens for instructions */
144%token <temp_inst> BIN_OP BINSC_OP SAMPLE_OP SCALAR_OP TRI_OP VECTOR_OP
Ian Romanickede0cd42009-08-31 17:00:31 -0700145%token <temp_inst> ARL KIL SWZ TXD_OP
Ian Romanick770cebb2009-07-20 17:44:36 -0700146
147%token <integer> INTEGER
148%token <real> REAL
149
150%token AMBIENT ATTENUATION
151%token BACK
152%token CLIP COLOR
153%token DEPTH DIFFUSE DIRECTION
154%token EMISSION ENV EYE
155%token FOG FOGCOORD FRAGMENT FRONT
156%token HALF
157%token INVERSE INVTRANS
158%token LIGHT LIGHTMODEL LIGHTPROD LOCAL
159%token MATERIAL MAT_PROGRAM MATRIX MATRIXINDEX MODELVIEW MVP
160%token NORMAL
161%token OBJECT
162%token PALETTE PARAMS PLANE POINT POINTSIZE POSITION PRIMARY PROGRAM PROJECTION
163%token RANGE RESULT ROW
164%token SCENECOLOR SECONDARY SHININESS SIZE SPECULAR SPOT STATE
165%token TEXCOORD TEXENV TEXGEN TEXGEN_Q TEXGEN_R TEXGEN_S TEXGEN_T TEXTURE TRANSPOSE
166%token TEXTURE_UNIT TEX_1D TEX_2D TEX_3D TEX_CUBE TEX_RECT
Ian Romanick1edd13b2009-07-27 16:24:49 -0700167%token TEX_SHADOW1D TEX_SHADOW2D TEX_SHADOWRECT
Ian Romanickaafd5762009-07-27 17:22:21 -0700168%token TEX_ARRAY1D TEX_ARRAY2D TEX_ARRAYSHADOW1D TEX_ARRAYSHADOW2D
Ian Romanick770cebb2009-07-20 17:44:36 -0700169%token VERTEX VTXATTRIB
170%token WEIGHT
171
172%token <string> IDENTIFIER
173%token <swiz_mask> MASK4 MASK3 MASK2 MASK1 SWIZZLE
174%token DOT_DOT
175%token DOT
176
177%type <inst> instruction ALU_instruction TexInstruction
178%type <inst> ARL_instruction VECTORop_instruction
179%type <inst> SCALARop_instruction BINSCop_instruction BINop_instruction
Ian Romanick8ca6fd82009-09-01 14:16:03 -0700180%type <inst> TRIop_instruction TXD_instruction SWZ_instruction SAMPLE_instruction
Ian Romanick770cebb2009-07-20 17:44:36 -0700181%type <inst> KIL_instruction
182
183%type <dst_reg> dstReg maskedDstReg maskedAddrReg
184%type <src_reg> srcReg scalarSrcReg swizzleSrcReg
Ian Romanick565a2a82009-07-30 10:51:43 -0700185%type <swiz_mask> scalarSuffix swizzleSuffix extendedSwizzle
186%type <ext_swizzle> extSwizComp extSwizSel
Ian Romanick770cebb2009-07-20 17:44:36 -0700187%type <swiz_mask> optionalMask
Ian Romanick770cebb2009-07-20 17:44:36 -0700188
189%type <sym> progParamArray
190%type <integer> addrRegRelOffset addrRegPosOffset addrRegNegOffset
191%type <src_reg> progParamArrayMem progParamArrayAbs progParamArrayRel
192%type <sym> addrReg
193%type <swiz_mask> addrComponent addrWriteMask
194
195%type <result> resultBinding resultColBinding
196%type <integer> optFaceType optColorType
197%type <integer> optResultFaceType optResultColorType
198
199%type <integer> optTexImageUnitNum texImageUnitNum
200%type <integer> optTexCoordUnitNum texCoordUnitNum
201%type <integer> optLegacyTexUnitNum legacyTexUnitNum
202%type <integer> texImageUnit texTarget
203%type <integer> vtxAttribNum
204
205%type <attrib> attribBinding vtxAttribItem fragAttribItem
206
207%type <temp_sym> paramSingleInit paramSingleItemDecl
208%type <integer> optArraySize
209
210%type <state> stateSingleItem stateMultipleItem
211%type <state> stateMaterialItem
212%type <state> stateLightItem stateLightModelItem stateLightProdItem
213%type <state> stateTexGenItem stateFogItem stateClipPlaneItem statePointItem
214%type <state> stateMatrixItem stateMatrixRow stateMatrixRows
Ian Romanick333bb4f2009-07-29 20:41:48 -0700215%type <state> stateTexEnvItem stateDepthItem
Ian Romanick770cebb2009-07-20 17:44:36 -0700216
217%type <state> stateLModProperty
218%type <state> stateMatrixName optMatrixRows
219
220%type <integer> stateMatProperty
221%type <integer> stateLightProperty stateSpotProperty
222%type <integer> stateLightNumber stateLProdProperty
223%type <integer> stateTexGenType stateTexGenCoord
224%type <integer> stateTexEnvProperty
225%type <integer> stateFogProperty
226%type <integer> stateClipPlaneNum
227%type <integer> statePointProperty
228
229%type <integer> stateOptMatModifier stateMatModifier stateMatrixRowNum
230%type <integer> stateOptModMatNum stateModMatNum statePaletteMatNum
231%type <integer> stateProgramMatNum
232
233%type <integer> ambDiffSpecProperty
234
235%type <state> programSingleItem progEnvParam progLocalParam
236%type <state> programMultipleItem progEnvParams progLocalParams
237
238%type <temp_sym> paramMultipleInit paramMultInitList paramMultipleItem
239%type <temp_sym> paramSingleItemUse
240
241%type <integer> progEnvParamNum progLocalParamNum
242%type <state> progEnvParamNums progLocalParamNums
243
244%type <vector> paramConstDecl paramConstUse
245%type <vector> paramConstScalarDecl paramConstScalarUse paramConstVector
246%type <real> signedFloatConstant
247%type <negate> optionalSign
248
249%{
250extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
251 void *yyscanner);
252%}
253
254%%
255
256program: language optionSequence statementSequence END
257 ;
258
259language: ARBvp_10
260 {
261 if (state->prog->Target != GL_VERTEX_PROGRAM_ARB) {
262 yyerror(& @1, state, "invalid fragment program header");
263
264 }
265 state->mode = ARB_vertex;
266 }
267 | ARBfp_10
268 {
269 if (state->prog->Target != GL_FRAGMENT_PROGRAM_ARB) {
270 yyerror(& @1, state, "invalid vertex program header");
271 }
272 state->mode = ARB_fragment;
Ian Romanick88018e22009-07-27 15:47:52 -0700273
274 state->option.TexRect =
275 (state->ctx->Extensions.NV_texture_rectangle != GL_FALSE);
Ian Romanick770cebb2009-07-20 17:44:36 -0700276 }
277 ;
278
279optionSequence: optionSequence option
280 |
281 ;
282
283option: OPTION IDENTIFIER ';'
284 {
285 int valid = 0;
286
287 if (state->mode == ARB_vertex) {
288 valid = _mesa_ARBvp_parse_option(state, $2);
289 } else if (state->mode == ARB_fragment) {
290 valid = _mesa_ARBfp_parse_option(state, $2);
291 }
292
293
294 if (!valid) {
Ian Romanick41d56962009-07-27 16:33:16 -0700295 const char *const err_str = (state->mode == ARB_vertex)
296 ? "invalid ARB vertex program option"
297 : "invalid ARB fragment program option";
298
299 yyerror(& @2, state, err_str);
Ian Romanick770cebb2009-07-20 17:44:36 -0700300 YYERROR;
301 }
302 }
303 ;
304
305statementSequence: statementSequence statement
306 |
307 ;
308
309statement: instruction ';'
310 {
311 if ($1 != NULL) {
312 if (state->inst_tail == NULL) {
313 state->inst_head = $1;
314 } else {
315 state->inst_tail->next = $1;
316 }
317
318 state->inst_tail = $1;
319 $1->next = NULL;
320
321 state->prog->NumInstructions++;
322 }
323 }
324 | namingStatement ';'
325 ;
326
327instruction: ALU_instruction
Ian Romanick0db5ef02009-07-22 16:21:54 -0700328 {
329 $$ = $1;
330 state->prog->NumAluInstructions++;
331 }
Ian Romanick770cebb2009-07-20 17:44:36 -0700332 | TexInstruction
Ian Romanick0db5ef02009-07-22 16:21:54 -0700333 {
334 $$ = $1;
335 state->prog->NumTexInstructions++;
336 }
Ian Romanick770cebb2009-07-20 17:44:36 -0700337 ;
338
339ALU_instruction: ARL_instruction
340 | VECTORop_instruction
341 | SCALARop_instruction
342 | BINSCop_instruction
343 | BINop_instruction
344 | TRIop_instruction
345 | SWZ_instruction
346 ;
347
348TexInstruction: SAMPLE_instruction
349 | KIL_instruction
Ian Romanick8ca6fd82009-09-01 14:16:03 -0700350 | TXD_instruction
Ian Romanick770cebb2009-07-20 17:44:36 -0700351 ;
352
353ARL_instruction: ARL maskedAddrReg ',' scalarSrcReg
354 {
355 $$ = asm_instruction_ctor(OPCODE_ARL, & $2, & $4, NULL, NULL);
356 }
357 ;
358
359VECTORop_instruction: VECTOR_OP maskedDstReg ',' swizzleSrcReg
360 {
361 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
362 $$->Base.SaturateMode = $1.SaturateMode;
363 }
364 ;
365
366SCALARop_instruction: SCALAR_OP maskedDstReg ',' scalarSrcReg
367 {
368 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
369 $$->Base.SaturateMode = $1.SaturateMode;
370 }
371 ;
372
373BINSCop_instruction: BINSC_OP maskedDstReg ',' scalarSrcReg ',' scalarSrcReg
374 {
375 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
376 $$->Base.SaturateMode = $1.SaturateMode;
377 }
378 ;
379
380
381BINop_instruction: BIN_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg
382 {
383 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
384 $$->Base.SaturateMode = $1.SaturateMode;
385 }
386 ;
387
388TRIop_instruction: TRI_OP maskedDstReg ','
389 swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg
390 {
391 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, & $8);
392 $$->Base.SaturateMode = $1.SaturateMode;
393 }
394 ;
395
396SAMPLE_instruction: SAMPLE_OP maskedDstReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget
397 {
398 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
399 if ($$ != NULL) {
Ian Romanick1edd13b2009-07-27 16:24:49 -0700400 const GLbitfield tex_mask = (1U << $6);
401 GLbitfield shadow_tex = 0;
402 GLbitfield target_mask = 0;
403
404
Ian Romanick770cebb2009-07-20 17:44:36 -0700405 $$->Base.SaturateMode = $1.SaturateMode;
406 $$->Base.TexSrcUnit = $6;
Ian Romanick0db5ef02009-07-22 16:21:54 -0700407
Ian Romanick1edd13b2009-07-27 16:24:49 -0700408 if ($8 < 0) {
409 shadow_tex = tex_mask;
410
411 $$->Base.TexSrcTarget = -$8;
412 $$->Base.TexShadow = 1;
413 } else {
414 $$->Base.TexSrcTarget = $8;
415 }
416
417 target_mask = (1U << $$->Base.TexSrcTarget);
418
419 /* If this texture unit was previously accessed and that access
420 * had a different texture target, generate an error.
421 *
422 * If this texture unit was previously accessed and that access
423 * had a different shadow mode, generate an error.
424 */
425 if ((state->prog->TexturesUsed[$6] != 0)
426 && ((state->prog->TexturesUsed[$6] != target_mask)
427 || ((state->prog->ShadowSamplers & tex_mask)
428 != shadow_tex))) {
429 yyerror(& @8, state,
430 "multiple targets used on one texture image unit");
431 YYERROR;
432 }
433
434
435 state->prog->TexturesUsed[$6] |= target_mask;
436 state->prog->ShadowSamplers |= shadow_tex;
Ian Romanick770cebb2009-07-20 17:44:36 -0700437 }
438 }
439 ;
440
441KIL_instruction: KIL swizzleSrcReg
442 {
443 $$ = asm_instruction_ctor(OPCODE_KIL, NULL, & $2, NULL, NULL);
Ian Romanick0db5ef02009-07-22 16:21:54 -0700444 state->fragment.UsesKill = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700445 }
446 ;
447
Ian Romanick8ca6fd82009-09-01 14:16:03 -0700448TXD_instruction: TXD_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget
449 {
450 $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, & $8);
451 if ($$ != NULL) {
452 const GLbitfield tex_mask = (1U << $10);
453 GLbitfield shadow_tex = 0;
454 GLbitfield target_mask = 0;
455
456
457 $$->Base.SaturateMode = $1.SaturateMode;
458 $$->Base.TexSrcUnit = $10;
459
460 if ($12 < 0) {
461 shadow_tex = tex_mask;
462
463 $$->Base.TexSrcTarget = -$12;
464 $$->Base.TexShadow = 1;
465 } else {
466 $$->Base.TexSrcTarget = $12;
467 }
468
469 target_mask = (1U << $$->Base.TexSrcTarget);
470
471 /* If this texture unit was previously accessed and that access
472 * had a different texture target, generate an error.
473 *
474 * If this texture unit was previously accessed and that access
475 * had a different shadow mode, generate an error.
476 */
477 if ((state->prog->TexturesUsed[$10] != 0)
478 && ((state->prog->TexturesUsed[$10] != target_mask)
479 || ((state->prog->ShadowSamplers & tex_mask)
480 != shadow_tex))) {
481 yyerror(& @12, state,
482 "multiple targets used on one texture image unit");
483 YYERROR;
484 }
485
486
487 state->prog->TexturesUsed[$10] |= target_mask;
488 state->prog->ShadowSamplers |= shadow_tex;
489 }
490 }
491 ;
492
Ian Romanick770cebb2009-07-20 17:44:36 -0700493texImageUnit: TEXTURE_UNIT optTexImageUnitNum
494 {
495 $$ = $2;
496 }
497 ;
498
499texTarget: TEX_1D { $$ = TEXTURE_1D_INDEX; }
500 | TEX_2D { $$ = TEXTURE_2D_INDEX; }
501 | TEX_3D { $$ = TEXTURE_3D_INDEX; }
502 | TEX_CUBE { $$ = TEXTURE_CUBE_INDEX; }
503 | TEX_RECT { $$ = TEXTURE_RECT_INDEX; }
Ian Romanick1edd13b2009-07-27 16:24:49 -0700504 | TEX_SHADOW1D { $$ = -TEXTURE_1D_INDEX; }
505 | TEX_SHADOW2D { $$ = -TEXTURE_2D_INDEX; }
506 | TEX_SHADOWRECT { $$ = -TEXTURE_RECT_INDEX; }
Ian Romanickaafd5762009-07-27 17:22:21 -0700507 | TEX_ARRAY1D { $$ = TEXTURE_1D_ARRAY_INDEX; }
508 | TEX_ARRAY2D { $$ = TEXTURE_2D_ARRAY_INDEX; }
509 | TEX_ARRAYSHADOW1D { $$ = -TEXTURE_1D_ARRAY_INDEX; }
510 | TEX_ARRAYSHADOW2D { $$ = -TEXTURE_2D_ARRAY_INDEX; }
Ian Romanick770cebb2009-07-20 17:44:36 -0700511 ;
512
513SWZ_instruction: SWZ maskedDstReg ',' srcReg ',' extendedSwizzle
514 {
515 /* FIXME: Is this correct? Should the extenedSwizzle be applied
516 * FIXME: to the existing swizzle?
517 */
518 $4.Base.Swizzle = $6.swizzle;
Ian Romanick648dac42009-07-28 21:57:28 -0700519 $4.Base.Negate = $6.mask;
Ian Romanick770cebb2009-07-20 17:44:36 -0700520
521 $$ = asm_instruction_ctor(OPCODE_SWZ, & $2, & $4, NULL, NULL);
522 $$->Base.SaturateMode = $1.SaturateMode;
523 }
524 ;
525
526scalarSrcReg: optionalSign srcReg scalarSuffix
527 {
528 $$ = $2;
529
530 if ($1) {
531 $$.Base.Negate = ~$$.Base.Negate;
532 }
533
534 $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
535 $3.swizzle);
536 }
Ian Romanickb8e389b2009-09-03 14:05:18 -0700537 | optionalSign paramConstScalarUse
538 {
539 struct asm_symbol temp_sym;
540
541 if (!state->option.NV_fragment) {
542 yyerror(& @2, state, "expected scalar suffix");
543 YYERROR;
544 }
545
546 memset(& temp_sym, 0, sizeof(temp_sym));
547 temp_sym.param_binding_begin = ~0;
548 initialize_symbol_from_const(state->prog, & temp_sym, & $2);
549
550 init_src_reg(& $$);
551 $$.Base.File = PROGRAM_CONSTANT;
552 $$.Base.Index = temp_sym.param_binding_begin;
553 }
Ian Romanick770cebb2009-07-20 17:44:36 -0700554 ;
555
556swizzleSrcReg: optionalSign srcReg swizzleSuffix
557 {
558 $$ = $2;
559
560 if ($1) {
561 $$.Base.Negate = ~$$.Base.Negate;
562 }
563
564 $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
565 $3.swizzle);
566 }
567 ;
568
569maskedDstReg: dstReg optionalMask
570 {
571 $$ = $1;
572 $$.WriteMask = $2.mask;
573
574 if ($$.File == PROGRAM_OUTPUT) {
575 /* Technically speaking, this should check that it is in
576 * vertex program mode. However, PositionInvariant can never be
577 * set in fragment program mode, so it is somewhat irrelevant.
578 */
579 if (state->option.PositionInvariant
580 && ($$.Index == VERT_RESULT_HPOS)) {
581 yyerror(& @1, state, "position-invariant programs cannot "
582 "write position");
583 YYERROR;
584 }
585
586 state->prog->OutputsWritten |= (1U << $$.Index);
587 }
588 }
589 ;
590
591maskedAddrReg: addrReg addrWriteMask
592 {
593 init_dst_reg(& $$);
594 $$.File = PROGRAM_ADDRESS;
595 $$.Index = 0;
596 $$.WriteMask = $2.mask;
597 }
598 ;
599
600extendedSwizzle: extSwizComp ',' extSwizComp ',' extSwizComp ',' extSwizComp
601 {
Ian Romanick565a2a82009-07-30 10:51:43 -0700602 const unsigned xyzw_valid =
603 ($1.xyzw_valid << 0)
604 | ($3.xyzw_valid << 1)
605 | ($5.xyzw_valid << 2)
606 | ($7.xyzw_valid << 3);
607 const unsigned rgba_valid =
608 ($1.rgba_valid << 0)
609 | ($3.rgba_valid << 1)
610 | ($5.rgba_valid << 2)
611 | ($7.rgba_valid << 3);
612
613 /* All of the swizzle components have to be valid in either RGBA
614 * or XYZW. Note that 0 and 1 are valid in both, so both masks
615 * can have some bits set.
616 *
617 * We somewhat deviate from the spec here. It would be really hard
618 * to figure out which component is the error, and there probably
619 * isn't a lot of benefit.
620 */
621 if ((rgba_valid != 0x0f) && (xyzw_valid != 0x0f)) {
622 yyerror(& @1, state, "cannot combine RGBA and XYZW swizzle "
623 "components");
624 YYERROR;
625 }
626
627 $$.swizzle = MAKE_SWIZZLE4($1.swz, $3.swz, $5.swz, $7.swz);
628 $$.mask = ($1.negate) | ($3.negate << 1) | ($5.negate << 2)
629 | ($7.negate << 3);
Ian Romanick770cebb2009-07-20 17:44:36 -0700630 }
631 ;
632
633extSwizComp: optionalSign extSwizSel
634 {
Ian Romanick565a2a82009-07-30 10:51:43 -0700635 $$ = $2;
636 $$.negate = ($1) ? 1 : 0;
Ian Romanick770cebb2009-07-20 17:44:36 -0700637 }
638 ;
639
640extSwizSel: INTEGER
641 {
642 if (($1 != 0) && ($1 != 1)) {
643 yyerror(& @1, state, "invalid extended swizzle selector");
644 YYERROR;
645 }
646
Ian Romanick565a2a82009-07-30 10:51:43 -0700647 $$.swz = ($1 == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
648
649 /* 0 and 1 are valid for both RGBA swizzle names and XYZW
650 * swizzle names.
651 */
652 $$.xyzw_valid = 1;
653 $$.rgba_valid = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700654 }
655 | IDENTIFIER
656 {
657 if (strlen($1) > 1) {
658 yyerror(& @1, state, "invalid extended swizzle selector");
659 YYERROR;
660 }
661
662 switch ($1[0]) {
663 case 'x':
Ian Romanick565a2a82009-07-30 10:51:43 -0700664 $$.swz = SWIZZLE_X;
665 $$.xyzw_valid = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700666 break;
667 case 'y':
Ian Romanick565a2a82009-07-30 10:51:43 -0700668 $$.swz = SWIZZLE_Y;
669 $$.xyzw_valid = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700670 break;
671 case 'z':
Ian Romanick565a2a82009-07-30 10:51:43 -0700672 $$.swz = SWIZZLE_Z;
673 $$.xyzw_valid = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700674 break;
675 case 'w':
Ian Romanick565a2a82009-07-30 10:51:43 -0700676 $$.swz = SWIZZLE_W;
677 $$.xyzw_valid = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -0700678 break;
Ian Romanick565a2a82009-07-30 10:51:43 -0700679
680 case 'r':
681 $$.swz = SWIZZLE_X;
682 $$.rgba_valid = 1;
683 break;
684 case 'g':
685 $$.swz = SWIZZLE_Y;
686 $$.rgba_valid = 1;
687 break;
688 case 'b':
689 $$.swz = SWIZZLE_Z;
690 $$.rgba_valid = 1;
691 break;
692 case 'a':
693 $$.swz = SWIZZLE_W;
694 $$.rgba_valid = 1;
695 break;
696
Ian Romanick770cebb2009-07-20 17:44:36 -0700697 default:
698 yyerror(& @1, state, "invalid extended swizzle selector");
699 YYERROR;
700 break;
701 }
702 }
703 ;
704
705srcReg: IDENTIFIER /* temporaryReg | progParamSingle */
706 {
707 struct asm_symbol *const s = (struct asm_symbol *)
708 _mesa_symbol_table_find_symbol(state->st, 0, $1);
709
710 if (s == NULL) {
711 yyerror(& @1, state, "invalid operand variable");
712 YYERROR;
713 } else if ((s->type != at_param) && (s->type != at_temp)
714 && (s->type != at_attrib)) {
715 yyerror(& @1, state, "invalid operand variable");
716 YYERROR;
717 } else if ((s->type == at_param) && s->param_is_array) {
718 yyerror(& @1, state, "non-array access to array PARAM");
719 YYERROR;
720 }
721
722 init_src_reg(& $$);
723 switch (s->type) {
724 case at_temp:
725 $$.Base.File = PROGRAM_TEMPORARY;
726 $$.Base.Index = s->temp_binding;
727 break;
728 case at_param:
729 $$.Base.File = s->param_binding_type;
730 $$.Base.Index = s->param_binding_begin;
731 break;
732 case at_attrib:
Ian Romanick8a430dd2009-07-29 09:50:06 -0700733 $$.Base.File = PROGRAM_INPUT;
734 $$.Base.Index = s->attrib_binding;
735 state->prog->InputsRead |= (1U << $$.Base.Index);
Ian Romanick770cebb2009-07-20 17:44:36 -0700736
Ian Romanick8a430dd2009-07-29 09:50:06 -0700737 if (!validate_inputs(& @1, state)) {
738 YYERROR;
739 }
740 break;
Ian Romanick770cebb2009-07-20 17:44:36 -0700741
742 default:
743 YYERROR;
744 break;
745 }
746 }
747 | attribBinding
748 {
749 init_src_reg(& $$);
750 $$.Base.File = PROGRAM_INPUT;
751 $$.Base.Index = $1;
752 state->prog->InputsRead |= (1U << $$.Base.Index);
753
754 if (!validate_inputs(& @1, state)) {
755 YYERROR;
756 }
757 }
758 | progParamArray '[' progParamArrayMem ']'
759 {
760 if (! $3.Base.RelAddr
Ian Romanickef80c202009-07-22 17:13:08 -0700761 && ((unsigned) $3.Base.Index >= $1->param_binding_length)) {
Ian Romanick770cebb2009-07-20 17:44:36 -0700762 yyerror(& @3, state, "out of bounds array access");
763 YYERROR;
764 }
765
766 init_src_reg(& $$);
767 $$.Base.File = $1->param_binding_type;
768
769 if ($3.Base.RelAddr) {
770 $1->param_accessed_indirectly = 1;
771
772 $$.Base.RelAddr = 1;
773 $$.Base.Index = $3.Base.Index;
774 $$.Symbol = $1;
775 } else {
776 $$.Base.Index = $1->param_binding_begin + $3.Base.Index;
777 }
778 }
779 | paramSingleItemUse
780 {
781 init_src_reg(& $$);
Ian Romanick69d3d192009-07-22 10:51:18 -0700782 $$.Base.File = ($1.name != NULL)
783 ? $1.param_binding_type
784 : PROGRAM_CONSTANT;
Ian Romanick770cebb2009-07-20 17:44:36 -0700785 $$.Base.Index = $1.param_binding_begin;
786 }
787 ;
788
789dstReg: resultBinding
790 {
791 init_dst_reg(& $$);
792 $$.File = PROGRAM_OUTPUT;
793 $$.Index = $1;
794 }
795 | IDENTIFIER /* temporaryReg | vertexResultReg */
796 {
797 struct asm_symbol *const s = (struct asm_symbol *)
798 _mesa_symbol_table_find_symbol(state->st, 0, $1);
799
800 if (s == NULL) {
801 yyerror(& @1, state, "invalid operand variable");
802 YYERROR;
803 } else if ((s->type != at_output) && (s->type != at_temp)) {
804 yyerror(& @1, state, "invalid operand variable");
805 YYERROR;
806 }
807
808 init_dst_reg(& $$);
Ian Romanick86b33b52009-07-28 21:56:42 -0700809 switch (s->type) {
810 case at_temp:
Ian Romanick770cebb2009-07-20 17:44:36 -0700811 $$.File = PROGRAM_TEMPORARY;
812 $$.Index = s->temp_binding;
Ian Romanick86b33b52009-07-28 21:56:42 -0700813 break;
814 case at_output:
815 $$.File = PROGRAM_OUTPUT;
816 $$.Index = s->output_binding;
817 break;
818 default:
Ian Romanick770cebb2009-07-20 17:44:36 -0700819 $$.File = s->param_binding_type;
820 $$.Index = s->param_binding_begin;
Ian Romanick86b33b52009-07-28 21:56:42 -0700821 break;
Ian Romanick770cebb2009-07-20 17:44:36 -0700822 }
823 }
824 ;
825
826progParamArray: IDENTIFIER
827 {
828 struct asm_symbol *const s = (struct asm_symbol *)
829 _mesa_symbol_table_find_symbol(state->st, 0, $1);
830
831 if (s == NULL) {
832 yyerror(& @1, state, "invalid operand variable");
833 YYERROR;
834 } else if ((s->type != at_param) || !s->param_is_array) {
835 yyerror(& @1, state, "array access to non-PARAM variable");
836 YYERROR;
837 } else {
838 $$ = s;
839 }
840 }
841 ;
842
843progParamArrayMem: progParamArrayAbs | progParamArrayRel;
844
845progParamArrayAbs: INTEGER
846 {
847 init_src_reg(& $$);
848 $$.Base.Index = $1;
849 }
850 ;
851
852progParamArrayRel: addrReg addrComponent addrRegRelOffset
853 {
854 /* FINISHME: Add support for multiple address registers.
855 */
856 /* FINISHME: Add support for 4-component address registers.
857 */
858 init_src_reg(& $$);
859 $$.Base.RelAddr = 1;
860 $$.Base.Index = $3;
861 }
862 ;
863
864addrRegRelOffset: { $$ = 0; }
865 | '+' addrRegPosOffset { $$ = $2; }
866 | '-' addrRegNegOffset { $$ = -$2; }
867 ;
868
869addrRegPosOffset: INTEGER
870 {
871 if (($1 < 0) || ($1 > 63)) {
872 yyerror(& @1, state,
873 "relative address offset too large (positive)");
874 YYERROR;
875 } else {
876 $$ = $1;
877 }
878 }
879 ;
880
881addrRegNegOffset: INTEGER
882 {
883 if (($1 < 0) || ($1 > 64)) {
884 yyerror(& @1, state,
885 "relative address offset too large (negative)");
886 YYERROR;
887 } else {
888 $$ = $1;
889 }
890 }
891 ;
892
893addrReg: IDENTIFIER
894 {
895 struct asm_symbol *const s = (struct asm_symbol *)
896 _mesa_symbol_table_find_symbol(state->st, 0, $1);
897
898 if (s == NULL) {
899 yyerror(& @1, state, "invalid array member");
900 YYERROR;
901 } else if (s->type != at_address) {
902 yyerror(& @1, state,
903 "invalid variable for indexed array access");
904 YYERROR;
905 } else {
906 $$ = s;
907 }
908 }
909 ;
910
911addrComponent: MASK1
912 {
913 if ($1.mask != WRITEMASK_X) {
914 yyerror(& @1, state, "invalid address component selector");
915 YYERROR;
916 } else {
917 $$ = $1;
918 }
919 }
920 ;
921
922addrWriteMask: MASK1
923 {
924 if ($1.mask != WRITEMASK_X) {
925 yyerror(& @1, state,
926 "address register write mask must be \".x\"");
927 YYERROR;
928 } else {
929 $$ = $1;
930 }
931 }
932 ;
933
934scalarSuffix: MASK1;
935
936swizzleSuffix: MASK1
937 | MASK4
938 | SWIZZLE
939 | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
940 ;
941
942optionalMask: MASK4 | MASK3 | MASK2 | MASK1
943 | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
944 ;
945
946namingStatement: ATTRIB_statement
947 | PARAM_statement
948 | TEMP_statement
949 | ADDRESS_statement
950 | OUTPUT_statement
951 | ALIAS_statement
952 ;
953
954ATTRIB_statement: ATTRIB IDENTIFIER '=' attribBinding
955 {
956 struct asm_symbol *const s =
957 declare_variable(state, $2, at_attrib, & @2);
958
959 if (s == NULL) {
960 YYERROR;
961 } else {
962 s->attrib_binding = $4;
963 state->InputsBound |= (1U << s->attrib_binding);
964
965 if (!validate_inputs(& @4, state)) {
966 YYERROR;
967 }
968 }
969 }
970 ;
971
972attribBinding: VERTEX vtxAttribItem
973 {
974 $$ = $2;
975 }
976 | FRAGMENT fragAttribItem
977 {
978 $$ = $2;
979 }
980 ;
981
982vtxAttribItem: POSITION
983 {
984 $$ = VERT_ATTRIB_POS;
985 }
986 | WEIGHT vtxOptWeightNum
987 {
988 $$ = VERT_ATTRIB_WEIGHT;
989 }
990 | NORMAL
991 {
992 $$ = VERT_ATTRIB_NORMAL;
993 }
994 | COLOR optColorType
995 {
Ian Romanick054ab5a2009-07-27 14:11:38 -0700996 if (!state->ctx->Extensions.EXT_secondary_color) {
997 yyerror(& @2, state, "GL_EXT_secondary_color not supported");
998 YYERROR;
999 }
1000
Ian Romanick770cebb2009-07-20 17:44:36 -07001001 $$ = VERT_ATTRIB_COLOR0 + $2;
1002 }
1003 | FOGCOORD
1004 {
Ian Romanick054ab5a2009-07-27 14:11:38 -07001005 if (!state->ctx->Extensions.EXT_fog_coord) {
1006 yyerror(& @1, state, "GL_EXT_fog_coord not supported");
1007 YYERROR;
1008 }
1009
Ian Romanick770cebb2009-07-20 17:44:36 -07001010 $$ = VERT_ATTRIB_FOG;
1011 }
1012 | TEXCOORD optTexCoordUnitNum
1013 {
1014 $$ = VERT_ATTRIB_TEX0 + $2;
1015 }
1016 | MATRIXINDEX '[' vtxWeightNum ']'
1017 {
Ian Romanick054ab5a2009-07-27 14:11:38 -07001018 yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
Ian Romanick770cebb2009-07-20 17:44:36 -07001019 YYERROR;
1020 }
1021 | VTXATTRIB '[' vtxAttribNum ']'
1022 {
1023 $$ = VERT_ATTRIB_GENERIC0 + $3;
1024 }
1025 ;
1026
1027vtxAttribNum: INTEGER
1028 {
Ian Romanickef80c202009-07-22 17:13:08 -07001029 if ((unsigned) $1 >= state->limits->MaxAttribs) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001030 yyerror(& @1, state, "invalid vertex attribute reference");
1031 YYERROR;
1032 }
1033
1034 $$ = $1;
1035 }
1036 ;
1037
1038vtxOptWeightNum: | '[' vtxWeightNum ']';
1039vtxWeightNum: INTEGER;
1040
1041fragAttribItem: POSITION
1042 {
1043 $$ = FRAG_ATTRIB_WPOS;
1044 }
1045 | COLOR optColorType
1046 {
1047 $$ = FRAG_ATTRIB_COL0 + $2;
1048 }
1049 | FOGCOORD
1050 {
1051 $$ = FRAG_ATTRIB_FOGC;
1052 }
1053 | TEXCOORD optTexCoordUnitNum
1054 {
1055 $$ = FRAG_ATTRIB_TEX0 + $2;
1056 }
1057 ;
1058
1059PARAM_statement: PARAM_singleStmt | PARAM_multipleStmt;
1060
1061PARAM_singleStmt: PARAM IDENTIFIER paramSingleInit
1062 {
1063 struct asm_symbol *const s =
1064 declare_variable(state, $2, at_param, & @2);
1065
1066 if (s == NULL) {
1067 YYERROR;
1068 } else {
1069 s->param_binding_type = $3.param_binding_type;
1070 s->param_binding_begin = $3.param_binding_begin;
1071 s->param_binding_length = $3.param_binding_length;
1072 s->param_is_array = 0;
1073 }
1074 }
1075 ;
1076
1077PARAM_multipleStmt: PARAM IDENTIFIER '[' optArraySize ']' paramMultipleInit
1078 {
Ian Romanickef80c202009-07-22 17:13:08 -07001079 if (($4 != 0) && ((unsigned) $4 != $6.param_binding_length)) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001080 yyerror(& @4, state,
1081 "parameter array size and number of bindings must match");
1082 YYERROR;
1083 } else {
1084 struct asm_symbol *const s =
1085 declare_variable(state, $2, $6.type, & @2);
1086
1087 if (s == NULL) {
1088 YYERROR;
1089 } else {
1090 s->param_binding_type = $6.param_binding_type;
1091 s->param_binding_begin = $6.param_binding_begin;
1092 s->param_binding_length = $6.param_binding_length;
1093 s->param_is_array = 1;
1094 }
1095 }
1096 }
1097 ;
1098
1099optArraySize:
1100 {
1101 $$ = 0;
1102 }
1103 | INTEGER
1104 {
Ian Romanickef80c202009-07-22 17:13:08 -07001105 if (($1 < 1) || ((unsigned) $1 >= state->limits->MaxParameters)) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001106 yyerror(& @1, state, "invalid parameter array size");
1107 YYERROR;
1108 } else {
1109 $$ = $1;
1110 }
1111 }
1112 ;
1113
1114paramSingleInit: '=' paramSingleItemDecl
1115 {
1116 $$ = $2;
1117 }
1118 ;
1119
1120paramMultipleInit: '=' '{' paramMultInitList '}'
1121 {
1122 $$ = $3;
1123 }
1124 ;
1125
1126paramMultInitList: paramMultipleItem
1127 | paramMultInitList ',' paramMultipleItem
1128 {
1129 $1.param_binding_length += $3.param_binding_length;
1130 $$ = $1;
1131 }
1132 ;
1133
1134paramSingleItemDecl: stateSingleItem
1135 {
1136 memset(& $$, 0, sizeof($$));
1137 $$.param_binding_begin = ~0;
1138 initialize_symbol_from_state(state->prog, & $$, $1);
1139 }
1140 | programSingleItem
1141 {
1142 memset(& $$, 0, sizeof($$));
1143 $$.param_binding_begin = ~0;
1144 initialize_symbol_from_param(state->prog, & $$, $1);
1145 }
1146 | paramConstDecl
1147 {
1148 memset(& $$, 0, sizeof($$));
1149 $$.param_binding_begin = ~0;
1150 initialize_symbol_from_const(state->prog, & $$, & $1);
1151 }
1152 ;
1153
1154paramSingleItemUse: stateSingleItem
1155 {
1156 memset(& $$, 0, sizeof($$));
1157 $$.param_binding_begin = ~0;
1158 initialize_symbol_from_state(state->prog, & $$, $1);
1159 }
1160 | programSingleItem
1161 {
1162 memset(& $$, 0, sizeof($$));
1163 $$.param_binding_begin = ~0;
1164 initialize_symbol_from_param(state->prog, & $$, $1);
1165 }
1166 | paramConstUse
1167 {
1168 memset(& $$, 0, sizeof($$));
1169 $$.param_binding_begin = ~0;
1170 initialize_symbol_from_const(state->prog, & $$, & $1);
1171 }
1172 ;
1173
1174paramMultipleItem: stateMultipleItem
1175 {
1176 memset(& $$, 0, sizeof($$));
1177 $$.param_binding_begin = ~0;
1178 initialize_symbol_from_state(state->prog, & $$, $1);
1179 }
1180 | programMultipleItem
1181 {
1182 memset(& $$, 0, sizeof($$));
1183 $$.param_binding_begin = ~0;
1184 initialize_symbol_from_param(state->prog, & $$, $1);
1185 }
1186 | paramConstDecl
1187 {
1188 memset(& $$, 0, sizeof($$));
1189 $$.param_binding_begin = ~0;
1190 initialize_symbol_from_const(state->prog, & $$, & $1);
1191 }
1192 ;
1193
1194stateMultipleItem: stateSingleItem { memcpy($$, $1, sizeof($$)); }
1195 | STATE stateMatrixRows { memcpy($$, $2, sizeof($$)); }
1196 ;
1197
1198stateSingleItem: STATE stateMaterialItem { memcpy($$, $2, sizeof($$)); }
1199 | STATE stateLightItem { memcpy($$, $2, sizeof($$)); }
1200 | STATE stateLightModelItem { memcpy($$, $2, sizeof($$)); }
1201 | STATE stateLightProdItem { memcpy($$, $2, sizeof($$)); }
1202 | STATE stateTexGenItem { memcpy($$, $2, sizeof($$)); }
1203 | STATE stateTexEnvItem { memcpy($$, $2, sizeof($$)); }
1204 | STATE stateFogItem { memcpy($$, $2, sizeof($$)); }
1205 | STATE stateClipPlaneItem { memcpy($$, $2, sizeof($$)); }
1206 | STATE statePointItem { memcpy($$, $2, sizeof($$)); }
1207 | STATE stateMatrixRow { memcpy($$, $2, sizeof($$)); }
Ian Romanick333bb4f2009-07-29 20:41:48 -07001208 | STATE stateDepthItem { memcpy($$, $2, sizeof($$)); }
Ian Romanick770cebb2009-07-20 17:44:36 -07001209 ;
1210
1211stateMaterialItem: MATERIAL optFaceType stateMatProperty
1212 {
1213 memset($$, 0, sizeof($$));
1214 $$[0] = STATE_MATERIAL;
1215 $$[1] = $2;
1216 $$[2] = $3;
1217 }
1218 ;
1219
1220stateMatProperty: ambDiffSpecProperty
1221 {
1222 $$ = $1;
1223 }
1224 | EMISSION
1225 {
1226 $$ = STATE_EMISSION;
1227 }
1228 | SHININESS
1229 {
1230 $$ = STATE_SHININESS;
1231 }
1232 ;
1233
1234stateLightItem: LIGHT '[' stateLightNumber ']' stateLightProperty
1235 {
1236 memset($$, 0, sizeof($$));
1237 $$[0] = STATE_LIGHT;
1238 $$[1] = $3;
1239 $$[2] = $5;
1240 }
1241 ;
1242
1243stateLightProperty: ambDiffSpecProperty
1244 {
1245 $$ = $1;
1246 }
1247 | POSITION
1248 {
1249 $$ = STATE_POSITION;
1250 }
1251 | ATTENUATION
1252 {
Ian Romanick054ab5a2009-07-27 14:11:38 -07001253 if (!state->ctx->Extensions.EXT_point_parameters) {
1254 yyerror(& @1, state, "GL_ARB_point_parameters not supported");
1255 YYERROR;
1256 }
1257
Ian Romanick770cebb2009-07-20 17:44:36 -07001258 $$ = STATE_ATTENUATION;
1259 }
1260 | SPOT stateSpotProperty
1261 {
1262 $$ = $2;
1263 }
1264 | HALF
1265 {
1266 $$ = STATE_HALF_VECTOR;
1267 }
1268 ;
1269
1270stateSpotProperty: DIRECTION
1271 {
1272 $$ = STATE_SPOT_DIRECTION;
1273 }
1274 ;
1275
1276stateLightModelItem: LIGHTMODEL stateLModProperty
1277 {
1278 $$[0] = $2[0];
1279 $$[1] = $2[1];
1280 }
1281 ;
1282
1283stateLModProperty: AMBIENT
1284 {
1285 memset($$, 0, sizeof($$));
1286 $$[0] = STATE_LIGHTMODEL_AMBIENT;
1287 }
1288 | optFaceType SCENECOLOR
1289 {
1290 memset($$, 0, sizeof($$));
1291 $$[0] = STATE_LIGHTMODEL_SCENECOLOR;
1292 $$[1] = $1;
1293 }
1294 ;
1295
1296stateLightProdItem: LIGHTPROD '[' stateLightNumber ']' optFaceType stateLProdProperty
1297 {
1298 memset($$, 0, sizeof($$));
1299 $$[0] = STATE_LIGHTPROD;
1300 $$[1] = $3;
1301 $$[2] = $5;
1302 $$[3] = $6;
1303 }
1304 ;
1305
1306stateLProdProperty: ambDiffSpecProperty;
1307
1308stateTexEnvItem: TEXENV optLegacyTexUnitNum stateTexEnvProperty
1309 {
1310 memset($$, 0, sizeof($$));
1311 $$[0] = $3;
1312 $$[1] = $2;
1313 }
1314 ;
1315
1316stateTexEnvProperty: COLOR
1317 {
1318 $$ = STATE_TEXENV_COLOR;
1319 }
1320 ;
1321
1322ambDiffSpecProperty: AMBIENT
1323 {
1324 $$ = STATE_AMBIENT;
1325 }
1326 | DIFFUSE
1327 {
1328 $$ = STATE_DIFFUSE;
1329 }
1330 | SPECULAR
1331 {
1332 $$ = STATE_SPECULAR;
1333 }
1334 ;
1335
1336stateLightNumber: INTEGER
1337 {
Ian Romanickef80c202009-07-22 17:13:08 -07001338 if ((unsigned) $1 >= state->MaxLights) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001339 yyerror(& @1, state, "invalid light selector");
1340 YYERROR;
1341 }
1342
1343 $$ = $1;
1344 }
1345 ;
1346
1347stateTexGenItem: TEXGEN optTexCoordUnitNum stateTexGenType stateTexGenCoord
1348 {
1349 memset($$, 0, sizeof($$));
1350 $$[0] = STATE_TEXGEN;
1351 $$[1] = $2;
1352 $$[2] = $3 + $4;
1353 }
1354 ;
1355
1356stateTexGenType: EYE
1357 {
1358 $$ = STATE_TEXGEN_EYE_S;
1359 }
1360 | OBJECT
1361 {
1362 $$ = STATE_TEXGEN_OBJECT_S;
1363 }
1364 ;
1365stateTexGenCoord: TEXGEN_S
1366 {
1367 $$ = STATE_TEXGEN_EYE_S - STATE_TEXGEN_EYE_S;
1368 }
1369 | TEXGEN_T
1370 {
1371 $$ = STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S;
1372 }
1373 | TEXGEN_R
1374 {
1375 $$ = STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S;
1376 }
1377 | TEXGEN_Q
1378 {
1379 $$ = STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S;
1380 }
1381 ;
1382
1383stateFogItem: FOG stateFogProperty
1384 {
1385 memset($$, 0, sizeof($$));
1386 $$[0] = $2;
1387 }
1388 ;
1389
1390stateFogProperty: COLOR
1391 {
1392 $$ = STATE_FOG_COLOR;
1393 }
1394 | PARAMS
1395 {
1396 $$ = STATE_FOG_PARAMS;
1397 }
1398 ;
1399
1400stateClipPlaneItem: CLIP '[' stateClipPlaneNum ']' PLANE
1401 {
1402 memset($$, 0, sizeof($$));
1403 $$[0] = STATE_CLIPPLANE;
1404 $$[1] = $3;
1405 }
1406 ;
1407
1408stateClipPlaneNum: INTEGER
1409 {
Ian Romanickef80c202009-07-22 17:13:08 -07001410 if ((unsigned) $1 >= state->MaxClipPlanes) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001411 yyerror(& @1, state, "invalid clip plane selector");
1412 YYERROR;
1413 }
1414
1415 $$ = $1;
1416 }
1417 ;
1418
1419statePointItem: POINT statePointProperty
1420 {
1421 memset($$, 0, sizeof($$));
1422 $$[0] = $2;
1423 }
1424 ;
1425
1426statePointProperty: SIZE
1427 {
1428 $$ = STATE_POINT_SIZE;
1429 }
1430 | ATTENUATION
1431 {
1432 $$ = STATE_POINT_ATTENUATION;
1433 }
1434 ;
1435
1436stateMatrixRow: stateMatrixItem ROW '[' stateMatrixRowNum ']'
1437 {
1438 $$[0] = $1[0];
1439 $$[1] = $1[1];
1440 $$[2] = $4;
1441 $$[3] = $4;
1442 $$[4] = $1[2];
1443 }
1444 ;
1445
1446stateMatrixRows: stateMatrixItem optMatrixRows
1447 {
1448 $$[0] = $1[0];
1449 $$[1] = $1[1];
1450 $$[2] = $2[2];
1451 $$[3] = $2[3];
1452 $$[4] = $1[2];
1453 }
1454 ;
1455
1456optMatrixRows:
1457 {
1458 $$[2] = 0;
1459 $$[3] = 3;
1460 }
1461 | ROW '[' stateMatrixRowNum DOT_DOT stateMatrixRowNum ']'
1462 {
1463 /* It seems logical that the matrix row range specifier would have
1464 * to specify a range or more than one row (i.e., $5 > $3).
1465 * However, the ARB_vertex_program spec says "a program will fail
1466 * to load if <a> is greater than <b>." This means that $3 == $5
1467 * is valid.
1468 */
1469 if ($3 > $5) {
1470 yyerror(& @3, state, "invalid matrix row range");
1471 YYERROR;
1472 }
1473
1474 $$[2] = $3;
1475 $$[3] = $5;
1476 }
1477 ;
1478
1479stateMatrixItem: MATRIX stateMatrixName stateOptMatModifier
1480 {
1481 $$[0] = $2[0];
1482 $$[1] = $2[1];
1483 $$[2] = $3;
1484 }
1485 ;
1486
1487stateOptMatModifier:
1488 {
1489 $$ = 0;
1490 }
1491 | stateMatModifier
1492 {
1493 $$ = $1;
1494 }
1495 ;
1496
1497stateMatModifier: INVERSE
1498 {
1499 $$ = STATE_MATRIX_INVERSE;
1500 }
1501 | TRANSPOSE
1502 {
1503 $$ = STATE_MATRIX_TRANSPOSE;
1504 }
1505 | INVTRANS
1506 {
1507 $$ = STATE_MATRIX_INVTRANS;
1508 }
1509 ;
1510
1511stateMatrixRowNum: INTEGER
1512 {
1513 if ($1 > 3) {
1514 yyerror(& @1, state, "invalid matrix row reference");
1515 YYERROR;
1516 }
1517
1518 $$ = $1;
1519 }
1520 ;
1521
1522stateMatrixName: MODELVIEW stateOptModMatNum
1523 {
1524 $$[0] = STATE_MODELVIEW_MATRIX;
1525 $$[1] = $2;
1526 }
1527 | PROJECTION
1528 {
1529 $$[0] = STATE_PROJECTION_MATRIX;
1530 $$[1] = 0;
1531 }
1532 | MVP
1533 {
1534 $$[0] = STATE_MVP_MATRIX;
1535 $$[1] = 0;
1536 }
1537 | TEXTURE optTexCoordUnitNum
1538 {
1539 $$[0] = STATE_TEXTURE_MATRIX;
1540 $$[1] = $2;
1541 }
1542 | PALETTE '[' statePaletteMatNum ']'
1543 {
Ian Romanick054ab5a2009-07-27 14:11:38 -07001544 yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
Ian Romanick770cebb2009-07-20 17:44:36 -07001545 YYERROR;
1546 }
1547 | MAT_PROGRAM '[' stateProgramMatNum ']'
1548 {
1549 $$[0] = STATE_PROGRAM_MATRIX;
1550 $$[1] = $3;
1551 }
1552 ;
1553
1554stateOptModMatNum:
1555 {
1556 $$ = 0;
1557 }
1558 | stateModMatNum
1559 {
1560 $$ = $1;
1561 }
1562 ;
1563stateModMatNum: INTEGER
1564 {
1565 /* Since GL_ARB_vertex_blend isn't supported, only modelview matrix
1566 * zero is valid.
1567 */
1568 if ($1 != 0) {
1569 yyerror(& @1, state, "invalid modelview matrix index");
1570 YYERROR;
1571 }
1572
1573 $$ = $1;
1574 }
1575 ;
1576statePaletteMatNum: INTEGER
1577 {
1578 /* Since GL_ARB_matrix_palette isn't supported, just let any value
1579 * through here. The error will be generated later.
1580 */
1581 $$ = $1;
1582 }
1583 ;
1584stateProgramMatNum: INTEGER
1585 {
Ian Romanickef80c202009-07-22 17:13:08 -07001586 if ((unsigned) $1 >= state->MaxProgramMatrices) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001587 yyerror(& @1, state, "invalid program matrix selector");
1588 YYERROR;
1589 }
1590
1591 $$ = $1;
1592 }
1593 ;
1594
Ian Romanick333bb4f2009-07-29 20:41:48 -07001595stateDepthItem: DEPTH RANGE
1596 {
1597 memset($$, 0, sizeof($$));
1598 $$[0] = STATE_DEPTH_RANGE;
1599 }
1600 ;
Ian Romanick770cebb2009-07-20 17:44:36 -07001601
1602
1603programSingleItem: progEnvParam | progLocalParam;
1604
1605programMultipleItem: progEnvParams | progLocalParams;
1606
1607progEnvParams: PROGRAM ENV '[' progEnvParamNums ']'
1608 {
1609 memset($$, 0, sizeof($$));
1610 $$[0] = state->state_param_enum;
1611 $$[1] = STATE_ENV;
1612 $$[2] = $4[0];
1613 $$[3] = $4[1];
1614 }
1615 ;
1616
1617progEnvParamNums: progEnvParamNum
1618 {
1619 $$[0] = $1;
1620 $$[1] = $1;
1621 }
1622 | progEnvParamNum DOT_DOT progEnvParamNum
1623 {
1624 $$[0] = $1;
1625 $$[1] = $3;
1626 }
1627 ;
1628
1629progEnvParam: PROGRAM ENV '[' progEnvParamNum ']'
1630 {
1631 memset($$, 0, sizeof($$));
1632 $$[0] = state->state_param_enum;
1633 $$[1] = STATE_ENV;
1634 $$[2] = $4;
1635 $$[3] = $4;
1636 }
1637 ;
1638
1639progLocalParams: PROGRAM LOCAL '[' progLocalParamNums ']'
1640 {
1641 memset($$, 0, sizeof($$));
1642 $$[0] = state->state_param_enum;
1643 $$[1] = STATE_LOCAL;
1644 $$[2] = $4[0];
1645 $$[3] = $4[1];
1646 }
1647
1648progLocalParamNums: progLocalParamNum
1649 {
1650 $$[0] = $1;
1651 $$[1] = $1;
1652 }
1653 | progLocalParamNum DOT_DOT progLocalParamNum
1654 {
1655 $$[0] = $1;
1656 $$[1] = $3;
1657 }
1658 ;
1659
1660progLocalParam: PROGRAM LOCAL '[' progLocalParamNum ']'
1661 {
1662 memset($$, 0, sizeof($$));
1663 $$[0] = state->state_param_enum;
1664 $$[1] = STATE_LOCAL;
1665 $$[2] = $4;
1666 $$[3] = $4;
1667 }
1668 ;
1669
1670progEnvParamNum: INTEGER
1671 {
Ian Romanickef80c202009-07-22 17:13:08 -07001672 if ((unsigned) $1 >= state->limits->MaxEnvParams) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001673 yyerror(& @1, state, "invalid environment parameter reference");
1674 YYERROR;
1675 }
1676 $$ = $1;
1677 }
1678 ;
1679
1680progLocalParamNum: INTEGER
1681 {
Ian Romanickef80c202009-07-22 17:13:08 -07001682 if ((unsigned) $1 >= state->limits->MaxLocalParams) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001683 yyerror(& @1, state, "invalid local parameter reference");
1684 YYERROR;
1685 }
1686 $$ = $1;
1687 }
1688 ;
1689
1690
1691
1692paramConstDecl: paramConstScalarDecl | paramConstVector;
1693paramConstUse: paramConstScalarUse | paramConstVector;
1694
1695paramConstScalarDecl: signedFloatConstant
1696 {
Ian Romanick60071092009-07-29 21:07:41 -07001697 $$.count = 4;
Ian Romanick770cebb2009-07-20 17:44:36 -07001698 $$.data[0] = $1;
Ian Romanick60071092009-07-29 21:07:41 -07001699 $$.data[1] = $1;
1700 $$.data[2] = $1;
1701 $$.data[3] = $1;
Ian Romanick770cebb2009-07-20 17:44:36 -07001702 }
1703 ;
1704
1705paramConstScalarUse: REAL
1706 {
Ian Romanickac5551f2009-08-20 18:29:41 -07001707 $$.count = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -07001708 $$.data[0] = $1;
Ian Romanickac5551f2009-08-20 18:29:41 -07001709 $$.data[1] = $1;
1710 $$.data[2] = $1;
1711 $$.data[3] = $1;
Ian Romanick770cebb2009-07-20 17:44:36 -07001712 }
1713 | INTEGER
1714 {
Ian Romanickac5551f2009-08-20 18:29:41 -07001715 $$.count = 1;
Ian Romanick770cebb2009-07-20 17:44:36 -07001716 $$.data[0] = (float) $1;
Ian Romanickac5551f2009-08-20 18:29:41 -07001717 $$.data[1] = (float) $1;
1718 $$.data[2] = (float) $1;
1719 $$.data[3] = (float) $1;
Ian Romanick770cebb2009-07-20 17:44:36 -07001720 }
1721 ;
1722
1723paramConstVector: '{' signedFloatConstant '}'
1724 {
Ian Romanick60071092009-07-29 21:07:41 -07001725 $$.count = 4;
Ian Romanick770cebb2009-07-20 17:44:36 -07001726 $$.data[0] = $2;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001727 $$.data[1] = 0.0f;
1728 $$.data[2] = 0.0f;
Ian Romanick60071092009-07-29 21:07:41 -07001729 $$.data[3] = 1.0f;
Ian Romanick770cebb2009-07-20 17:44:36 -07001730 }
1731 | '{' signedFloatConstant ',' signedFloatConstant '}'
1732 {
Ian Romanick60071092009-07-29 21:07:41 -07001733 $$.count = 4;
Ian Romanick770cebb2009-07-20 17:44:36 -07001734 $$.data[0] = $2;
1735 $$.data[1] = $4;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001736 $$.data[2] = 0.0f;
Ian Romanick60071092009-07-29 21:07:41 -07001737 $$.data[3] = 1.0f;
Ian Romanick770cebb2009-07-20 17:44:36 -07001738 }
1739 | '{' signedFloatConstant ',' signedFloatConstant ','
1740 signedFloatConstant '}'
1741 {
Ian Romanick60071092009-07-29 21:07:41 -07001742 $$.count = 4;
Ian Romanick770cebb2009-07-20 17:44:36 -07001743 $$.data[0] = $2;
1744 $$.data[1] = $4;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001745 $$.data[2] = $6;
Ian Romanick60071092009-07-29 21:07:41 -07001746 $$.data[3] = 1.0f;
Ian Romanick770cebb2009-07-20 17:44:36 -07001747 }
1748 | '{' signedFloatConstant ',' signedFloatConstant ','
1749 signedFloatConstant ',' signedFloatConstant '}'
1750 {
1751 $$.count = 4;
1752 $$.data[0] = $2;
1753 $$.data[1] = $4;
Ian Romanickf3cba9d2009-07-24 18:01:59 -07001754 $$.data[2] = $6;
1755 $$.data[3] = $8;
Ian Romanick770cebb2009-07-20 17:44:36 -07001756 }
1757 ;
1758
1759signedFloatConstant: optionalSign REAL
1760 {
1761 $$ = ($1) ? -$2 : $2;
1762 }
1763 | optionalSign INTEGER
1764 {
1765 $$ = (float)(($1) ? -$2 : $2);
1766 }
1767 ;
1768
1769optionalSign: '+' { $$ = FALSE; }
1770 | '-' { $$ = TRUE; }
1771 | { $$ = FALSE; }
1772 ;
1773
1774TEMP_statement: TEMP { $<integer>$ = $1; } varNameList
1775 ;
1776
1777ADDRESS_statement: ADDRESS { $<integer>$ = $1; } varNameList
1778 ;
1779
1780varNameList: varNameList ',' IDENTIFIER
1781 {
1782 if (!declare_variable(state, $3, $<integer>0, & @3)) {
1783 YYERROR;
1784 }
1785 }
1786 | IDENTIFIER
1787 {
1788 if (!declare_variable(state, $1, $<integer>0, & @1)) {
1789 YYERROR;
1790 }
1791 }
1792 ;
1793
1794OUTPUT_statement: OUTPUT IDENTIFIER '=' resultBinding
1795 {
1796 struct asm_symbol *const s =
1797 declare_variable(state, $2, at_output, & @2);
1798
1799 if (s == NULL) {
1800 YYERROR;
1801 } else {
1802 s->output_binding = $4;
1803 }
1804 }
1805 ;
1806
1807resultBinding: RESULT POSITION
1808 {
1809 if (state->mode == ARB_vertex) {
1810 $$ = VERT_RESULT_HPOS;
1811 } else {
1812 yyerror(& @2, state, "invalid program result name");
1813 YYERROR;
1814 }
1815 }
1816 | RESULT FOGCOORD
1817 {
1818 if (state->mode == ARB_vertex) {
1819 $$ = VERT_RESULT_FOGC;
1820 } else {
1821 yyerror(& @2, state, "invalid program result name");
1822 YYERROR;
1823 }
1824 }
1825 | RESULT resultColBinding
1826 {
1827 $$ = $2;
1828 }
1829 | RESULT POINTSIZE
1830 {
1831 if (state->mode == ARB_vertex) {
1832 $$ = VERT_RESULT_PSIZ;
1833 } else {
1834 yyerror(& @2, state, "invalid program result name");
1835 YYERROR;
1836 }
1837 }
1838 | RESULT TEXCOORD optTexCoordUnitNum
1839 {
1840 if (state->mode == ARB_vertex) {
1841 $$ = VERT_RESULT_TEX0 + $3;
1842 } else {
1843 yyerror(& @2, state, "invalid program result name");
1844 YYERROR;
1845 }
1846 }
1847 | RESULT DEPTH
1848 {
1849 if (state->mode == ARB_fragment) {
1850 $$ = FRAG_RESULT_DEPTH;
1851 } else {
1852 yyerror(& @2, state, "invalid program result name");
1853 YYERROR;
1854 }
1855 }
1856 ;
1857
1858resultColBinding: COLOR optResultFaceType optResultColorType
1859 {
1860 $$ = $2 + $3;
1861 }
1862 ;
1863
1864optResultFaceType:
1865 {
1866 $$ = (state->mode == ARB_vertex)
1867 ? VERT_RESULT_COL0
1868 : FRAG_RESULT_COLOR;
1869 }
1870 | FRONT
1871 {
1872 if (state->mode == ARB_vertex) {
1873 $$ = VERT_RESULT_COL0;
1874 } else {
1875 yyerror(& @1, state, "invalid program result name");
1876 YYERROR;
1877 }
1878 }
1879 | BACK
1880 {
1881 if (state->mode == ARB_vertex) {
1882 $$ = VERT_RESULT_BFC0;
1883 } else {
1884 yyerror(& @1, state, "invalid program result name");
1885 YYERROR;
1886 }
1887 }
1888 ;
1889
1890optResultColorType:
1891 {
1892 $$ = 0;
1893 }
1894 | PRIMARY
1895 {
1896 if (state->mode == ARB_vertex) {
1897 $$ = 0;
1898 } else {
1899 yyerror(& @1, state, "invalid program result name");
1900 YYERROR;
1901 }
1902 }
1903 | SECONDARY
1904 {
1905 if (state->mode == ARB_vertex) {
1906 $$ = 1;
1907 } else {
1908 yyerror(& @1, state, "invalid program result name");
1909 YYERROR;
1910 }
1911 }
1912 ;
1913
1914optFaceType: { $$ = 0; }
1915 | FRONT { $$ = 0; }
1916 | BACK { $$ = 1; }
1917 ;
1918
1919optColorType: { $$ = 0; }
1920 | PRIMARY { $$ = 0; }
1921 | SECONDARY { $$ = 1; }
1922 ;
1923
1924optTexCoordUnitNum: { $$ = 0; }
1925 | '[' texCoordUnitNum ']' { $$ = $2; }
1926 ;
1927
1928optTexImageUnitNum: { $$ = 0; }
1929 | '[' texImageUnitNum ']' { $$ = $2; }
1930 ;
1931
1932optLegacyTexUnitNum: { $$ = 0; }
1933 | '[' legacyTexUnitNum ']' { $$ = $2; }
1934 ;
1935
1936texCoordUnitNum: INTEGER
1937 {
Ian Romanickef80c202009-07-22 17:13:08 -07001938 if ((unsigned) $1 >= state->MaxTextureCoordUnits) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001939 yyerror(& @1, state, "invalid texture coordinate unit selector");
1940 YYERROR;
1941 }
1942
1943 $$ = $1;
1944 }
1945 ;
1946
1947texImageUnitNum: INTEGER
1948 {
Ian Romanickef80c202009-07-22 17:13:08 -07001949 if ((unsigned) $1 >= state->MaxTextureImageUnits) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001950 yyerror(& @1, state, "invalid texture image unit selector");
1951 YYERROR;
1952 }
1953
1954 $$ = $1;
1955 }
1956 ;
1957
1958legacyTexUnitNum: INTEGER
1959 {
Ian Romanickef80c202009-07-22 17:13:08 -07001960 if ((unsigned) $1 >= state->MaxTextureUnits) {
Ian Romanick770cebb2009-07-20 17:44:36 -07001961 yyerror(& @1, state, "invalid texture unit selector");
1962 YYERROR;
1963 }
1964
1965 $$ = $1;
1966 }
1967 ;
1968
1969ALIAS_statement: ALIAS IDENTIFIER '=' IDENTIFIER
1970 {
1971 struct asm_symbol *exist = (struct asm_symbol *)
1972 _mesa_symbol_table_find_symbol(state->st, 0, $2);
1973 struct asm_symbol *target = (struct asm_symbol *)
1974 _mesa_symbol_table_find_symbol(state->st, 0, $4);
1975
1976
1977 if (exist != NULL) {
1978 yyerror(& @2, state, "redeclared identifier");
1979 YYERROR;
1980 } else if (target == NULL) {
1981 yyerror(& @4, state,
1982 "undefined variable binding in ALIAS statement");
1983 YYERROR;
1984 } else {
1985 _mesa_symbol_table_add_symbol(state->st, 0, $2, target);
1986 }
1987 }
1988 ;
1989
1990%%
1991
1992struct asm_instruction *
1993asm_instruction_ctor(gl_inst_opcode op,
1994 const struct prog_dst_register *dst,
1995 const struct asm_src_register *src0,
1996 const struct asm_src_register *src1,
1997 const struct asm_src_register *src2)
1998{
1999 struct asm_instruction *inst = calloc(1, sizeof(struct asm_instruction));
2000
2001 if (inst) {
Ian Romanickef80c202009-07-22 17:13:08 -07002002 _mesa_init_instructions(& inst->Base, 1);
Ian Romanick770cebb2009-07-20 17:44:36 -07002003 inst->Base.Opcode = op;
Ian Romanick17534ab2009-07-30 09:41:35 -07002004
2005 /* In the core ARB extensions only the KIL instruction doesn't have a
2006 * destination register.
2007 */
2008 if (dst == NULL) {
2009 init_dst_reg(& inst->Base.DstReg);
2010 } else {
2011 inst->Base.DstReg = *dst;
2012 }
Ian Romanick770cebb2009-07-20 17:44:36 -07002013
2014 inst->Base.SrcReg[0] = src0->Base;
2015 inst->SrcReg[0] = *src0;
2016
2017 if (src1 != NULL) {
2018 inst->Base.SrcReg[1] = src1->Base;
2019 inst->SrcReg[1] = *src1;
Ian Romanickaec42912009-07-22 12:29:48 -07002020 } else {
2021 init_src_reg(& inst->SrcReg[1]);
Ian Romanick770cebb2009-07-20 17:44:36 -07002022 }
2023
2024 if (src2 != NULL) {
2025 inst->Base.SrcReg[2] = src2->Base;
2026 inst->SrcReg[2] = *src2;
Ian Romanickaec42912009-07-22 12:29:48 -07002027 } else {
2028 init_src_reg(& inst->SrcReg[2]);
Ian Romanick770cebb2009-07-20 17:44:36 -07002029 }
2030 }
2031
2032 return inst;
2033}
2034
2035
2036void
2037init_dst_reg(struct prog_dst_register *r)
2038{
2039 memset(r, 0, sizeof(*r));
2040 r->File = PROGRAM_UNDEFINED;
2041 r->WriteMask = WRITEMASK_XYZW;
2042 r->CondMask = COND_TR;
2043 r->CondSwizzle = SWIZZLE_NOOP;
2044}
2045
2046
2047void
2048init_src_reg(struct asm_src_register *r)
2049{
2050 memset(r, 0, sizeof(*r));
2051 r->Base.File = PROGRAM_UNDEFINED;
2052 r->Base.Swizzle = SWIZZLE_NOOP;
2053 r->Symbol = NULL;
2054}
2055
2056
2057/**
2058 * Validate the set of inputs used by a program
2059 *
2060 * Validates that legal sets of inputs are used by the program. In this case
2061 * "used" included both reading the input or binding the input to a name using
2062 * the \c ATTRIB command.
2063 *
2064 * \return
2065 * \c TRUE if the combination of inputs used is valid, \c FALSE otherwise.
2066 */
2067int
2068validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
2069{
2070 const int inputs = state->prog->InputsRead | state->InputsBound;
2071
2072 if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
2073 yyerror(locp, state, "illegal use of generic attribute and name attribute");
2074 return 0;
2075 }
2076
2077 return 1;
2078}
2079
2080
2081struct asm_symbol *
2082declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
2083 struct YYLTYPE *locp)
2084{
2085 struct asm_symbol *s = NULL;
2086 struct asm_symbol *exist = (struct asm_symbol *)
2087 _mesa_symbol_table_find_symbol(state->st, 0, name);
2088
2089
2090 if (exist != NULL) {
2091 yyerror(locp, state, "redeclared identifier");
2092 } else {
2093 s = calloc(1, sizeof(struct asm_symbol));
2094 s->name = name;
2095 s->type = t;
2096
2097 switch (t) {
2098 case at_temp:
2099 if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
2100 yyerror(locp, state, "too many temporaries declared");
2101 free(s);
2102 return NULL;
2103 }
2104
2105 s->temp_binding = state->prog->NumTemporaries;
2106 state->prog->NumTemporaries++;
2107 break;
2108
2109 case at_address:
2110 if (state->prog->NumAddressRegs >= state->limits->MaxAddressRegs) {
2111 yyerror(locp, state, "too many address registers declared");
2112 free(s);
2113 return NULL;
2114 }
2115
2116 /* FINISHME: Add support for multiple address registers.
2117 */
2118 state->prog->NumAddressRegs++;
2119 break;
2120
2121 default:
2122 break;
2123 }
2124
2125 _mesa_symbol_table_add_symbol(state->st, 0, s->name, s);
Ian Romanick94b45562009-07-27 12:21:26 -07002126 s->next = state->sym;
2127 state->sym = s;
Ian Romanick770cebb2009-07-20 17:44:36 -07002128 }
2129
2130 return s;
2131}
2132
2133
2134int add_state_reference(struct gl_program_parameter_list *param_list,
2135 const gl_state_index tokens[STATE_LENGTH])
2136{
2137 const GLuint size = 4; /* XXX fix */
2138 char *name;
2139 GLint index;
2140
2141 name = _mesa_program_state_string(tokens);
2142 index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
2143 size, GL_NONE,
2144 NULL, (gl_state_index *) tokens, 0x0);
2145 param_list->StateFlags |= _mesa_program_state_flags(tokens);
2146
2147 /* free name string here since we duplicated it in add_parameter() */
2148 _mesa_free(name);
2149
2150 return index;
2151}
2152
2153
2154int
2155initialize_symbol_from_state(struct gl_program *prog,
2156 struct asm_symbol *param_var,
2157 const gl_state_index tokens[STATE_LENGTH])
2158{
2159 int idx = -1;
2160 gl_state_index state_tokens[STATE_LENGTH];
2161
2162
2163 memcpy(state_tokens, tokens, sizeof(state_tokens));
2164
2165 param_var->type = at_param;
Ian Romanick28b13032009-07-22 16:03:32 -07002166 param_var->param_binding_type = PROGRAM_STATE_VAR;
Ian Romanick770cebb2009-07-20 17:44:36 -07002167
2168 /* If we are adding a STATE_MATRIX that has multiple rows, we need to
2169 * unroll it and call add_state_reference() for each row
2170 */
2171 if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
2172 state_tokens[0] == STATE_PROJECTION_MATRIX ||
2173 state_tokens[0] == STATE_MVP_MATRIX ||
2174 state_tokens[0] == STATE_TEXTURE_MATRIX ||
2175 state_tokens[0] == STATE_PROGRAM_MATRIX)
2176 && (state_tokens[2] != state_tokens[3])) {
2177 int row;
2178 const int first_row = state_tokens[2];
2179 const int last_row = state_tokens[3];
2180
2181 for (row = first_row; row <= last_row; row++) {
2182 state_tokens[2] = state_tokens[3] = row;
2183
2184 idx = add_state_reference(prog->Parameters, state_tokens);
2185 if (param_var->param_binding_begin == ~0U)
2186 param_var->param_binding_begin = idx;
2187 param_var->param_binding_length++;
2188 }
2189 }
2190 else {
2191 idx = add_state_reference(prog->Parameters, state_tokens);
2192 if (param_var->param_binding_begin == ~0U)
2193 param_var->param_binding_begin = idx;
2194 param_var->param_binding_length++;
2195 }
2196
2197 return idx;
2198}
2199
2200
2201int
2202initialize_symbol_from_param(struct gl_program *prog,
2203 struct asm_symbol *param_var,
2204 const gl_state_index tokens[STATE_LENGTH])
2205{
2206 int idx = -1;
2207 gl_state_index state_tokens[STATE_LENGTH];
2208
2209
2210 memcpy(state_tokens, tokens, sizeof(state_tokens));
2211
2212 assert((state_tokens[0] == STATE_VERTEX_PROGRAM)
2213 || (state_tokens[0] == STATE_FRAGMENT_PROGRAM));
2214 assert((state_tokens[1] == STATE_ENV)
2215 || (state_tokens[1] == STATE_LOCAL));
2216
2217 param_var->type = at_param;
Ian Romanick28b13032009-07-22 16:03:32 -07002218 param_var->param_binding_type = (state_tokens[1] == STATE_ENV)
2219 ? PROGRAM_ENV_PARAM : PROGRAM_LOCAL_PARAM;
Ian Romanick770cebb2009-07-20 17:44:36 -07002220
2221 /* If we are adding a STATE_ENV or STATE_LOCAL that has multiple elements,
2222 * we need to unroll it and call add_state_reference() for each row
2223 */
2224 if (state_tokens[2] != state_tokens[3]) {
2225 int row;
2226 const int first_row = state_tokens[2];
2227 const int last_row = state_tokens[3];
2228
2229 for (row = first_row; row <= last_row; row++) {
2230 state_tokens[2] = state_tokens[3] = row;
2231
2232 idx = add_state_reference(prog->Parameters, state_tokens);
2233 if (param_var->param_binding_begin == ~0U)
2234 param_var->param_binding_begin = idx;
2235 param_var->param_binding_length++;
2236 }
2237 }
2238 else {
2239 idx = add_state_reference(prog->Parameters, state_tokens);
2240 if (param_var->param_binding_begin == ~0U)
2241 param_var->param_binding_begin = idx;
2242 param_var->param_binding_length++;
2243 }
2244
2245 return idx;
2246}
2247
2248
2249int
2250initialize_symbol_from_const(struct gl_program *prog,
2251 struct asm_symbol *param_var,
2252 const struct asm_vector *vec)
2253{
2254 const int idx = _mesa_add_parameter(prog->Parameters, PROGRAM_CONSTANT,
2255 NULL, vec->count, GL_NONE, vec->data,
2256 NULL, 0x0);
2257
2258 param_var->type = at_param;
Ian Romanick28b13032009-07-22 16:03:32 -07002259 param_var->param_binding_type = PROGRAM_CONSTANT;
Ian Romanick770cebb2009-07-20 17:44:36 -07002260
2261 if (param_var->param_binding_begin == ~0U)
2262 param_var->param_binding_begin = idx;
2263 param_var->param_binding_length++;
2264
2265 return idx;
2266}
2267
2268
Ian Romanick44843c72009-07-22 15:06:49 -07002269char *
2270make_error_string(const char *fmt, ...)
2271{
2272 int length;
2273 char *str;
2274 va_list args;
2275
2276 va_start(args, fmt);
2277
2278 /* Call vsnprintf once to determine how large the final string is. Call it
2279 * again to do the actual formatting. from the vsnprintf manual page:
2280 *
2281 * Upon successful return, these functions return the number of
2282 * characters printed (not including the trailing '\0' used to end
2283 * output to strings).
2284 */
2285 length = 1 + vsnprintf(NULL, 0, fmt, args);
2286
2287 str = _mesa_malloc(length);
2288 if (str) {
2289 vsnprintf(str, length, fmt, args);
2290 }
2291
2292 va_end(args);
2293
2294 return str;
2295}
2296
2297
Ian Romanick770cebb2009-07-20 17:44:36 -07002298void
2299yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
2300{
Ian Romanick44843c72009-07-22 15:06:49 -07002301 char *err_str;
Ian Romanick770cebb2009-07-20 17:44:36 -07002302
Ian Romanick44843c72009-07-22 15:06:49 -07002303
2304 err_str = make_error_string("glProgramStringARB(%s)\n", s);
2305 if (err_str) {
2306 _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
2307 _mesa_free(err_str);
2308 }
2309
2310 err_str = make_error_string("line %u, char %u: error: %s\n",
2311 locp->first_line, locp->first_column, s);
2312 _mesa_set_program_error(state->ctx, locp->position, err_str);
2313
2314 if (err_str) {
2315 _mesa_free(err_str);
2316 }
Ian Romanick770cebb2009-07-20 17:44:36 -07002317}
2318
Ian Romanick44843c72009-07-22 15:06:49 -07002319
Ian Romanick770cebb2009-07-20 17:44:36 -07002320GLboolean
2321_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
2322 GLsizei len, struct asm_parser_state *state)
2323{
Ian Romanick770cebb2009-07-20 17:44:36 -07002324 struct asm_instruction *inst;
2325 unsigned i;
2326 GLubyte *strz;
Ian Romanick94b45562009-07-27 12:21:26 -07002327 GLboolean result = GL_FALSE;
2328 void *temp;
2329 struct asm_symbol *sym;
Ian Romanick770cebb2009-07-20 17:44:36 -07002330
Ian Romanick44843c72009-07-22 15:06:49 -07002331 state->ctx = ctx;
Ian Romanick770cebb2009-07-20 17:44:36 -07002332 state->prog->Target = target;
2333 state->prog->Parameters = _mesa_new_parameter_list();
2334
2335 /* Make a copy of the program string and force it to be NUL-terminated.
2336 */
2337 strz = (GLubyte *) _mesa_malloc(len + 1);
2338 if (strz == NULL) {
2339 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
2340 return GL_FALSE;
2341 }
2342 _mesa_memcpy (strz, str, len);
2343 strz[len] = '\0';
2344
2345 state->prog->String = strz;
2346
2347 state->st = _mesa_symbol_table_ctor();
2348
Ian Romanick48183ca2009-07-29 20:51:38 -07002349 state->limits = (target == GL_VERTEX_PROGRAM_ARB)
2350 ? & ctx->Const.VertexProgram
2351 : & ctx->Const.FragmentProgram;
Ian Romanick770cebb2009-07-20 17:44:36 -07002352
Brian Paul4cf27602009-08-24 11:05:11 -06002353 state->MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
2354 state->MaxTextureCoordUnits = ctx->Const.MaxTextureCoordUnits;
2355 state->MaxTextureUnits = ctx->Const.MaxTextureUnits;
2356 state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
2357 state->MaxLights = ctx->Const.MaxLights;
2358 state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
Ian Romanick770cebb2009-07-20 17:44:36 -07002359
2360 state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
2361 ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
2362
2363 _mesa_set_program_error(ctx, -1, NULL);
2364
2365 _mesa_program_lexer_ctor(& state->scanner, state, (const char *) str, len);
2366 yyparse(state);
2367 _mesa_program_lexer_dtor(state->scanner);
2368
2369
Ian Romanick44843c72009-07-22 15:06:49 -07002370 if (ctx->Program.ErrorPos != -1) {
Ian Romanick94b45562009-07-27 12:21:26 -07002371 goto error;
Ian Romanick44843c72009-07-22 15:06:49 -07002372 }
2373
Ian Romanick770cebb2009-07-20 17:44:36 -07002374 if (! _mesa_layout_parameters(state)) {
Ian Romanick44843c72009-07-22 15:06:49 -07002375 struct YYLTYPE loc;
2376
2377 loc.first_line = 0;
2378 loc.first_column = 0;
2379 loc.position = len;
2380
2381 yyerror(& loc, state, "invalid PARAM usage");
Ian Romanick94b45562009-07-27 12:21:26 -07002382 goto error;
Ian Romanick770cebb2009-07-20 17:44:36 -07002383 }
2384
2385
2386
2387 /* Add one instruction to store the "END" instruction.
2388 */
2389 state->prog->Instructions =
2390 _mesa_alloc_instructions(state->prog->NumInstructions + 1);
2391 inst = state->inst_head;
2392 for (i = 0; i < state->prog->NumInstructions; i++) {
2393 struct asm_instruction *const temp = inst->next;
2394
2395 state->prog->Instructions[i] = inst->Base;
Ian Romanick770cebb2009-07-20 17:44:36 -07002396 inst = temp;
2397 }
2398
2399 /* Finally, tag on an OPCODE_END instruction */
2400 {
2401 const GLuint numInst = state->prog->NumInstructions;
2402 _mesa_init_instructions(state->prog->Instructions + numInst, 1);
2403 state->prog->Instructions[numInst].Opcode = OPCODE_END;
2404 }
2405 state->prog->NumInstructions++;
2406
Ian Romanickc2ee82d2009-07-22 15:27:31 -07002407 state->prog->NumParameters = state->prog->Parameters->NumParameters;
Ian Romanick4c5879f2009-07-29 09:47:14 -07002408 state->prog->NumAttributes = _mesa_bitcount(state->prog->InputsRead);
Ian Romanickc2ee82d2009-07-22 15:27:31 -07002409
Ian Romanick770cebb2009-07-20 17:44:36 -07002410 /*
2411 * Initialize native counts to logical counts. The device driver may
2412 * change them if program is translated into a hardware program.
2413 */
2414 state->prog->NumNativeInstructions = state->prog->NumInstructions;
2415 state->prog->NumNativeTemporaries = state->prog->NumTemporaries;
2416 state->prog->NumNativeParameters = state->prog->NumParameters;
2417 state->prog->NumNativeAttributes = state->prog->NumAttributes;
2418 state->prog->NumNativeAddressRegs = state->prog->NumAddressRegs;
2419
Ian Romanick94b45562009-07-27 12:21:26 -07002420 result = GL_TRUE;
2421
2422error:
2423 for (inst = state->inst_head; inst != NULL; inst = temp) {
2424 temp = inst->next;
2425 _mesa_free(inst);
2426 }
2427
2428 state->inst_head = NULL;
2429 state->inst_tail = NULL;
2430
2431 for (sym = state->sym; sym != NULL; sym = temp) {
2432 temp = sym->next;
2433
2434 _mesa_free((void *) sym->name);
2435 _mesa_free(sym);
2436 }
2437 state->sym = NULL;
2438
2439 _mesa_symbol_table_dtor(state->st);
2440 state->st = NULL;
2441
2442 return result;
Ian Romanick770cebb2009-07-20 17:44:36 -07002443}