mesa/formats: add more MESA_FORMAT_LAYOUTs
[mesa.git] / src / mesa / program / program_parse.y
index 784ea28c17a7275d8e6ceef28cd16154ce38e68d..635f5d09d6016f2001b1f484bf22157a7369b0aa 100644 (file)
@@ -21,6 +21,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -82,7 +84,7 @@ static void asm_instruction_set_operands(struct asm_instruction *inst,
     const struct prog_dst_register *dst, const struct asm_src_register *src0,
     const struct asm_src_register *src1, const struct asm_src_register *src2);
 
-static struct asm_instruction *asm_instruction_ctor(gl_inst_opcode op,
+static struct asm_instruction *asm_instruction_ctor(enum prog_opcode op,
     const struct prog_dst_register *dst, const struct asm_src_register *src0,
     const struct asm_src_register *src1, const struct asm_src_register *src2);
 
@@ -98,7 +100,7 @@ static struct asm_instruction *asm_instruction_copy_ctor(
 
 #define YYLLOC_DEFAULT(Current, Rhs, N)                                        \
    do {                                                                        \
-      if (YYID(N)) {                                                   \
+      if (N) {                                                 \
         (Current).first_line = YYRHSLOC(Rhs, 1).first_line;            \
         (Current).first_column = YYRHSLOC(Rhs, 1).first_column;        \
         (Current).position = YYRHSLOC(Rhs, 1).position;                \
@@ -112,16 +114,14 @@ static struct asm_instruction *asm_instruction_copy_ctor(
         (Current).position = YYRHSLOC(Rhs, 0).position                 \
            + (Current).first_column;                                   \
       }                                                                        \
-   } while(YYID(0))
-
-#define YYLEX_PARAM state->scanner
+   } while(0)
 %}
 
 %pure-parser
 %locations
+%lex-param   { struct asm_parser_state *state }
 %parse-param { struct asm_parser_state *state }
 %error-verbose
-%lex-param { void *scanner }
 
 %union {
    struct asm_instruction *inst;
@@ -139,7 +139,7 @@ static struct asm_instruction *asm_instruction_copy_ctor(
    gl_state_index state[STATE_LENGTH];
    int negate;
    struct asm_vector vector;
-   gl_inst_opcode opcode;
+   enum prog_opcode opcode;
 
    struct {
       unsigned swz;
@@ -269,8 +269,16 @@ static struct asm_instruction *asm_instruction_copy_ctor(
 %type <negate> optionalSign
 
 %{
-extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
-    void *yyscanner);
+extern int
+_mesa_program_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
+                        void *yyscanner);
+
+static int
+yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
+      struct asm_parser_state *state)
+{
+   return _mesa_program_lexer_lex(yylval_param, yylloc_param, state->scanner);
+}
 %}
 
 %%
@@ -382,6 +390,8 @@ ARL_instruction: ARL maskedAddrReg ',' scalarSrcReg
 
 VECTORop_instruction: VECTOR_OP maskedDstReg ',' swizzleSrcReg
        {
+          if ($1.Opcode == OPCODE_DDY)
+             state->fragment.UsesDFdy = 1;
           $$ = asm_instruction_copy_ctor(& $1, & $2, & $4, NULL, NULL);
        }
        ;
@@ -466,7 +476,6 @@ KIL_instruction: KIL swizzleSrcReg
           $$ = asm_instruction_ctor(OPCODE_KIL_NV, NULL, NULL, NULL, NULL);
           $$->Base.DstReg.CondMask = $2.CondMask;
           $$->Base.DstReg.CondSwizzle = $2.CondSwizzle;
-          $$->Base.DstReg.CondSrc = $2.CondSrc;
           state->fragment.UsesKill = 1;
        }
        ;
@@ -635,7 +644,6 @@ maskedDstReg: dstReg optionalMask optionalCcMask
           $$.WriteMask = $2.mask;
           $$.CondMask = $3.CondMask;
           $$.CondSwizzle = $3.CondSwizzle;
-          $$.CondSrc = $3.CondSrc;
 
           if ($$.File == PROGRAM_OUTPUT) {
              /* Technically speaking, this should check that it is in
@@ -643,7 +651,7 @@ maskedDstReg: dstReg optionalMask optionalCcMask
               * set in fragment program mode, so it is somewhat irrelevant.
               */
              if (state->option.PositionInvariant
-              && ($$.Index == VERT_RESULT_HPOS)) {
+              && ($$.Index == VARYING_SLOT_POS)) {
                 yyerror(& @1, state, "position-invariant programs cannot "
                         "write position");
                 YYERROR;
@@ -709,6 +717,7 @@ extSwizSel: INTEGER
           }
 
           $$.swz = ($1 == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
+           $$.negate = 0;
 
           /* 0 and 1 are valid for both RGBA swizzle names and XYZW
            * swizzle names.
@@ -728,6 +737,10 @@ extSwizSel: INTEGER
           s = $1[0];
           free($1);
 
+           $$.rgba_valid = 0;
+           $$.xyzw_valid = 0;
+           $$.negate = 0;
+
           switch (s) {
           case 'x':
              $$.swz = SWIZZLE_X;
@@ -802,7 +815,7 @@ srcReg: USED_IDENTIFIER /* temporaryReg | progParamSingle */
              break;
           case at_attrib:
              set_src_reg(& $$, PROGRAM_INPUT, s->attrib_binding);
-             state->prog->InputsRead |= (1U << $$.Base.Index);
+             state->prog->InputsRead |= BITFIELD64_BIT($$.Base.Index);
 
              if (!validate_inputs(& @1, state)) {
                 YYERROR;
@@ -817,7 +830,7 @@ srcReg: USED_IDENTIFIER /* temporaryReg | progParamSingle */
        | attribBinding
        {
           set_src_reg(& $$, PROGRAM_INPUT, $1);
-          state->prog->InputsRead |= (1U << $$.Base.Index);
+          state->prog->InputsRead |= BITFIELD64_BIT($$.Base.Index);
 
           if (!validate_inputs(& @1, state)) {
              YYERROR;
@@ -935,7 +948,7 @@ addrRegRelOffset:              { $$ = 0; }
 
 addrRegPosOffset: INTEGER
        {
-          if (($1 < 0) || ($1 > 4095)) {
+          if (($1 < 0) || ($1 > (state->limits->MaxAddressOffset - 1))) {
               char s[100];
               _mesa_snprintf(s, sizeof(s),
                              "relative address offset too large (%d)", $1);
@@ -949,7 +962,7 @@ addrRegPosOffset: INTEGER
 
 addrRegNegOffset: INTEGER
        {
-          if (($1 < 0) || ($1 > 4096)) {
+          if (($1 < 0) || ($1 > state->limits->MaxAddressOffset)) {
               char s[100];
               _mesa_snprintf(s, sizeof(s),
                              "relative address offset too large (%d)", $1);
@@ -1028,7 +1041,6 @@ optionalCcMask: '(' ccTest ')'
        {
           $$.CondMask = COND_TR;
           $$.CondSwizzle = SWIZZLE_NOOP;
-          $$.CondSrc = 0;
        }
        ;
 
@@ -1065,7 +1077,6 @@ ccMaskRule: IDENTIFIER
 
           $$.CondMask = cond;
           $$.CondSwizzle = SWIZZLE_NOOP;
-          $$.CondSrc = 0;
        }
        ;
 
@@ -1088,7 +1099,6 @@ ccMaskRule2: USED_IDENTIFIER
 
           $$.CondMask = cond;
           $$.CondSwizzle = SWIZZLE_NOOP;
-          $$.CondSrc = 0;
        }
        ;
 
@@ -1110,7 +1120,7 @@ ATTRIB_statement: ATTRIB IDENTIFIER '=' attribBinding
              YYERROR;
           } else {
              s->attrib_binding = $4;
-             state->InputsBound |= (1U << s->attrib_binding);
+             state->InputsBound |= BITFIELD64_BIT(s->attrib_binding);
 
              if (!validate_inputs(& @4, state)) {
                 YYERROR;
@@ -1143,20 +1153,10 @@ vtxAttribItem: POSITION
        }
        | COLOR optColorType
        {
-          if (!state->ctx->Extensions.EXT_secondary_color) {
-             yyerror(& @2, state, "GL_EXT_secondary_color not supported");
-             YYERROR;
-          }
-
           $$ = VERT_ATTRIB_COLOR0 + $2;
        }
        | FOGCOORD
        {
-          if (!state->ctx->Extensions.EXT_fog_coord) {
-             yyerror(& @1, state, "GL_EXT_fog_coord not supported");
-             YYERROR;
-          }
-
           $$ = VERT_ATTRIB_FOG;
        }
        | TEXCOORD optTexCoordUnitNum
@@ -1190,19 +1190,19 @@ vtxWeightNum: INTEGER;
 
 fragAttribItem: POSITION
        {
-          $$ = FRAG_ATTRIB_WPOS;
+          $$ = VARYING_SLOT_POS;
        }
        | COLOR optColorType
        {
-          $$ = FRAG_ATTRIB_COL0 + $2;
+          $$ = VARYING_SLOT_COL0 + $2;
        }
        | FOGCOORD
        {
-          $$ = FRAG_ATTRIB_FOGC;
+          $$ = VARYING_SLOT_FOGC;
        }
        | TEXCOORD optTexCoordUnitNum
        {
-          $$ = FRAG_ATTRIB_TEX0 + $2;
+          $$ = VARYING_SLOT_TEX0 + $2;
        }
        ;
 
@@ -1258,7 +1258,11 @@ optArraySize:
        | INTEGER
         {
           if (($1 < 1) || ((unsigned) $1 > state->limits->MaxParameters)) {
-             yyerror(& @1, state, "invalid parameter array size");
+              char msg[100];
+              _mesa_snprintf(msg, sizeof(msg),
+                             "invalid parameter array size (size=%d max=%u)",
+                             $1, state->limits->MaxParameters);
+             yyerror(& @1, state, msg);
              YYERROR;
           } else {
              $$ = $1;
@@ -1850,64 +1854,64 @@ paramConstUse: paramConstScalarUse | paramConstVector;
 paramConstScalarDecl: signedFloatConstant
        {
           $$.count = 4;
-          $$.data[0] = $1;
-          $$.data[1] = $1;
-          $$.data[2] = $1;
-          $$.data[3] = $1;
+          $$.data[0].f = $1;
+          $$.data[1].f = $1;
+          $$.data[2].f = $1;
+          $$.data[3].f = $1;
        }
        ;
 
 paramConstScalarUse: REAL
        {
           $$.count = 1;
-          $$.data[0] = $1;
-          $$.data[1] = $1;
-          $$.data[2] = $1;
-          $$.data[3] = $1;
+          $$.data[0].f = $1;
+          $$.data[1].f = $1;
+          $$.data[2].f = $1;
+          $$.data[3].f = $1;
        }
        | INTEGER
        {
           $$.count = 1;
-          $$.data[0] = (float) $1;
-          $$.data[1] = (float) $1;
-          $$.data[2] = (float) $1;
-          $$.data[3] = (float) $1;
+          $$.data[0].f = (float) $1;
+          $$.data[1].f = (float) $1;
+          $$.data[2].f = (float) $1;
+          $$.data[3].f = (float) $1;
        }
        ;
 
 paramConstVector: '{' signedFloatConstant '}'
        {
           $$.count = 4;
-          $$.data[0] = $2;
-          $$.data[1] = 0.0f;
-          $$.data[2] = 0.0f;
-          $$.data[3] = 1.0f;
+          $$.data[0].f = $2;
+          $$.data[1].f = 0.0f;
+          $$.data[2].f = 0.0f;
+          $$.data[3].f = 1.0f;
        }
        | '{' signedFloatConstant ',' signedFloatConstant '}'
        {
           $$.count = 4;
-          $$.data[0] = $2;
-          $$.data[1] = $4;
-          $$.data[2] = 0.0f;
-          $$.data[3] = 1.0f;
+          $$.data[0].f = $2;
+          $$.data[1].f = $4;
+          $$.data[2].f = 0.0f;
+          $$.data[3].f = 1.0f;
        }
        | '{' signedFloatConstant ',' signedFloatConstant ','
               signedFloatConstant '}'
        {
           $$.count = 4;
-          $$.data[0] = $2;
-          $$.data[1] = $4;
-          $$.data[2] = $6;
-          $$.data[3] = 1.0f;
+          $$.data[0].f = $2;
+          $$.data[1].f = $4;
+          $$.data[2].f = $6;
+          $$.data[3].f = 1.0f;
        }
        | '{' signedFloatConstant ',' signedFloatConstant ','
               signedFloatConstant ',' signedFloatConstant '}'
        {
           $$.count = 4;
-          $$.data[0] = $2;
-          $$.data[1] = $4;
-          $$.data[2] = $6;
-          $$.data[3] = $8;
+          $$.data[0].f = $2;
+          $$.data[1].f = $4;
+          $$.data[2].f = $6;
+          $$.data[3].f = $8;
        }
        ;
 
@@ -2004,7 +2008,7 @@ OUTPUT_statement: optVarSize OUTPUT IDENTIFIER '=' resultBinding
 resultBinding: RESULT POSITION
        {
           if (state->mode == ARB_vertex) {
-             $$ = VERT_RESULT_HPOS;
+             $$ = VARYING_SLOT_POS;
           } else {
              yyerror(& @2, state, "invalid program result name");
              YYERROR;
@@ -2013,7 +2017,7 @@ resultBinding: RESULT POSITION
        | RESULT FOGCOORD
        {
           if (state->mode == ARB_vertex) {
-             $$ = VERT_RESULT_FOGC;
+             $$ = VARYING_SLOT_FOGC;
           } else {
              yyerror(& @2, state, "invalid program result name");
              YYERROR;
@@ -2026,7 +2030,7 @@ resultBinding: RESULT POSITION
        | RESULT POINTSIZE
        {
           if (state->mode == ARB_vertex) {
-             $$ = VERT_RESULT_PSIZ;
+             $$ = VARYING_SLOT_PSIZ;
           } else {
              yyerror(& @2, state, "invalid program result name");
              YYERROR;
@@ -2035,7 +2039,7 @@ resultBinding: RESULT POSITION
        | RESULT TEXCOORD optTexCoordUnitNum
        {
           if (state->mode == ARB_vertex) {
-             $$ = VERT_RESULT_TEX0 + $3;
+             $$ = VARYING_SLOT_TEX0 + $3;
           } else {
              yyerror(& @2, state, "invalid program result name");
              YYERROR;
@@ -2060,14 +2064,47 @@ resultColBinding: COLOR optResultFaceType optResultColorType
 
 optResultFaceType:
        {
-          $$ = (state->mode == ARB_vertex)
-             ? VERT_RESULT_COL0
-             : FRAG_RESULT_COLOR;
+          if (state->mode == ARB_vertex) {
+             $$ = VARYING_SLOT_COL0;
+          } else {
+             if (state->option.DrawBuffers)
+                $$ = FRAG_RESULT_DATA0;
+             else
+                $$ = FRAG_RESULT_COLOR;
+          }
+       }
+       | '[' INTEGER ']'
+       {
+          if (state->mode == ARB_vertex) {
+             yyerror(& @1, state, "invalid program result name");
+             YYERROR;
+          } else {
+             if (!state->option.DrawBuffers) {
+                /* From the ARB_draw_buffers spec (same text exists
+                 * for ATI_draw_buffers):
+                 *
+                 *     If this option is not specified, a fragment
+                 *     program that attempts to bind
+                 *     "result.color[n]" will fail to load, and only
+                 *     "result.color" will be allowed.
+                 */
+                yyerror(& @1, state,
+                        "result.color[] used without "
+                        "`OPTION ARB_draw_buffers' or "
+                        "`OPTION ATI_draw_buffers'");
+                YYERROR;
+             } else if ($2 >= state->MaxDrawBuffers) {
+                yyerror(& @1, state,
+                        "result.color[] exceeds MAX_DRAW_BUFFERS_ARB");
+                YYERROR;
+             }
+             $$ = FRAG_RESULT_DATA0 + $2;
+          }
        }
        | FRONT
        {
           if (state->mode == ARB_vertex) {
-             $$ = VERT_RESULT_COL0;
+             $$ = VARYING_SLOT_COL0;
           } else {
              yyerror(& @1, state, "invalid program result name");
              YYERROR;
@@ -2076,7 +2113,7 @@ optResultFaceType:
        | BACK
        {
           if (state->mode == ARB_vertex) {
-             $$ = VERT_RESULT_BFC0;
+             $$ = VARYING_SLOT_BFC0;
           } else {
              yyerror(& @1, state, "invalid program result name");
              YYERROR;
@@ -2238,7 +2275,7 @@ asm_instruction_set_operands(struct asm_instruction *inst,
 
 
 struct asm_instruction *
-asm_instruction_ctor(gl_inst_opcode op,
+asm_instruction_ctor(enum prog_opcode op,
                     const struct prog_dst_register *dst,
                     const struct asm_src_register *src0,
                     const struct asm_src_register *src1,
@@ -2271,7 +2308,7 @@ asm_instruction_copy_ctor(const struct prog_instruction *base,
       inst->Base.Opcode = base->Opcode;
       inst->Base.CondUpdate = base->CondUpdate;
       inst->Base.CondDst = base->CondDst;
-      inst->Base.SaturateMode = base->SaturateMode;
+      inst->Base.Saturate = base->Saturate;
       inst->Base.Precision = base->Precision;
 
       asm_instruction_set_operands(inst, dst, src0, src1, src2);
@@ -2298,11 +2335,11 @@ set_dst_reg(struct prog_dst_register *r, gl_register_file file, GLint index)
 {
    const GLint maxIndex = 1 << INST_INDEX_BITS;
    const GLint minIndex = 0;
-   ASSERT(index >= minIndex);
+   assert(index >= minIndex);
    (void) minIndex;
-   ASSERT(index <= maxIndex);
+   assert(index <= maxIndex);
    (void) maxIndex;
-   ASSERT(file == PROGRAM_TEMPORARY ||
+   assert(file == PROGRAM_TEMPORARY ||
          file == PROGRAM_ADDRESS ||
          file == PROGRAM_OUTPUT);
    memset(r, 0, sizeof(*r));
@@ -2340,10 +2377,10 @@ set_src_reg_swz(struct asm_src_register *r, gl_register_file file, GLint index,
 {
    const GLint maxIndex = (1 << INST_INDEX_BITS) - 1;
    const GLint minIndex = -(1 << INST_INDEX_BITS);
-   ASSERT(file < PROGRAM_FILE_MAX);
-   ASSERT(index >= minIndex);
+   assert(file < PROGRAM_FILE_MAX);
+   assert(index >= minIndex);
    (void) minIndex;
-   ASSERT(index <= maxIndex);
+   assert(index <= maxIndex);
    (void) maxIndex;
    memset(r, 0, sizeof(*r));
    r->Base.File = file;
@@ -2366,9 +2403,9 @@ set_src_reg_swz(struct asm_src_register *r, gl_register_file file, GLint index,
 int
 validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
 {
-   const int inputs = state->prog->InputsRead | state->InputsBound;
+   const GLbitfield64 inputs = state->prog->InputsRead | state->InputsBound;
 
-   if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
+   if (((inputs & VERT_BIT_FF_ALL) & (inputs >> VERT_ATTRIB_GENERIC0)) != 0) {
       yyerror(locp, state, "illegal use of generic attribute and name attribute");
       return 0;
    }
@@ -2439,7 +2476,7 @@ int add_state_reference(struct gl_program_parameter_list *param_list,
 
    name = _mesa_program_state_string(tokens);
    index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
-                               size, GL_NONE, NULL, tokens, 0x0);
+                               size, GL_NONE, NULL, tokens);
    param_list->StateFlags |= _mesa_program_state_flags(tokens);
 
    /* free name string here since we duplicated it in add_parameter() */
@@ -2672,15 +2709,16 @@ _mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *st
    state->st = _mesa_symbol_table_ctor();
 
    state->limits = (target == GL_VERTEX_PROGRAM_ARB)
-      ? & ctx->Const.VertexProgram
-      : & ctx->Const.FragmentProgram;
+      ? & ctx->Const.Program[MESA_SHADER_VERTEX]
+      : & ctx->Const.Program[MESA_SHADER_FRAGMENT];
 
-   state->MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+   state->MaxTextureImageUnits = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits;
    state->MaxTextureCoordUnits = ctx->Const.MaxTextureCoordUnits;
    state->MaxTextureUnits = ctx->Const.MaxTextureUnits;
    state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
    state->MaxLights = ctx->Const.MaxLights;
    state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+   state->MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
 
    state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
       ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
@@ -2713,6 +2751,11 @@ _mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *st
     */
    state->prog->Instructions =
       _mesa_alloc_instructions(state->prog->NumInstructions + 1);
+
+   if (state->prog->Instructions == NULL) {
+      goto error;
+   }
+
    inst = state->inst_head;
    for (i = 0; i < state->prog->NumInstructions; i++) {
       struct asm_instruction *const temp = inst->next;
@@ -2730,7 +2773,7 @@ _mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *st
    state->prog->NumInstructions++;
 
    state->prog->NumParameters = state->prog->Parameters->NumParameters;
-   state->prog->NumAttributes = _mesa_bitcount(state->prog->InputsRead);
+   state->prog->NumAttributes = _mesa_bitcount_64(state->prog->InputsRead);
 
    /*
     * Initialize native counts to logical counts.  The device driver may