init secondary color to (0,0,0,1). remove some redundant initializations.
[mesa.git] / src / mesa / main / arbparse.c
index 25c1d7b7adaa18d1b61bad5823c9e4402f5dea39..fe08d48b94b49a12bc13cbfff11d302d597cf2ea 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.1
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -44,9 +44,6 @@
 /* TODO:
  *    Fragment Program Stuff:
  *    -----------------------------------------------------
- *    - How does negating on SWZ work?? If any of the components have a -,
- *      negate?
- *    - how does thing like 'foo[N]' work in src registers?
  *
  *    - things from Michal's email
  *       + overflow on atoi
  *
  *    Vertex Program Stuff:
  *    -----------------------------------------------------
- *    - throw an error if we mess with position and have  are position invar
+ *    - Optimize param array usage and count limits correctly, see spec,
+ *         section 2.14.3.7        
+ *       + Record if an array is reference absolutly or relatively (or both)
+ *       + For absolute arrays, store a bitmap of accesses
+ *       + For single parameters, store an access flag
+ *       + After parsing, make a parameter cleanup and merging pass, where
+ *           relative arrays are layed out first, followed by abs arrays, and
+ *           finally single state.
+ *       + Remap offsets for param src and dst registers
+ *       + Now we can properly count parameter usage
+ *                                                                         
+ *    - Multiple state binding errors in param arrays (see spec, just before
+ *         section 2.14.3.3)
  *    - grep for XXX
  *    
  *    Mesa Stuff
  *    -----------------------------------------------------
+ *    - User clipping planes vs. PositionInvariant 
+ *    - Is it sufficient to just multiply by the mvp to transform in the
+ *        PositionInvariant case? Or do we need something more involved?
+ *                    
  *    - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
  *    - fetch state listed in program_parameters list
  *       + WTF should this go???
@@ -2625,7 +2638,7 @@ grammar_check (dict * di, const GLubyte * text, GLubyte ** production,
       return 0;
    }
 
-   memcpy (*production, ba->data, ba->len * sizeof (GLubyte));
+   _mesa_memcpy(*production, ba->data, ba->len * sizeof (GLubyte));
    *size = ba->len;
    barray_destroy (&ba);
 
@@ -2916,7 +2929,7 @@ parse_float (GLubyte ** inst, struct arb_program *Program)
        * the .). We can have leading 0's here, which parse_integer will ignore, 
        * so we'll check for those first
        */
-   while (**inst == '0')
+   while ((**inst == '0') && ( *(*inst+1) != 0))
    {
          leading_zeros++;
          (*inst)++;
@@ -2929,13 +2942,13 @@ parse_float (GLubyte ** inst, struct arb_program *Program)
    denom = 1; 
    while (denom < tmp[2])
       denom *= 10;
-   denom *= _mesa_pow( 10, leading_zeros );
+   denom *= (GLint) _mesa_pow( 10, leading_zeros );
    value += (GLfloat) tmp[2] / (GLfloat) denom;
 #if 0
    if (tmp[0])
       value *= -1;
 #endif
-   value *= _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
+   value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
 
    return value;
 }
@@ -3502,7 +3515,7 @@ static GLuint
 parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
                            struct arb_program *Program, GLint * state_tokens)
 {
-   if (Program->type == GL_FRAGMENT_PROGRAM_ARB)
+   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
       state_tokens[0] = STATE_FRAGMENT_PROGRAM;
    else
       state_tokens[0] = STATE_VERTEX_PROGRAM;
@@ -3514,10 +3527,10 @@ parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
          state_tokens[2] = parse_integer (inst, Program);
 
          /* Check state_tokens[2] against the number of ENV parameters available */
-         if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
+         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
               (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
              ||
-             ((Program->type == GL_VERTEX_PROGRAM_ARB) &&
+             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
               (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
             _mesa_set_program_error (ctx, Program->Position,
                                      "Invalid Program Env Parameter");
@@ -3534,10 +3547,10 @@ parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
          state_tokens[2] = parse_integer (inst, Program);
 
          /* Check state_tokens[2] against the number of LOCAL parameters available */
-         if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
+         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
               (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
              ||
-             ((Program->type == GL_VERTEX_PROGRAM_ARB) &&
+             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
               (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
             _mesa_set_program_error (ctx, Program->Position,
                                      "Invalid Program Local Parameter");
@@ -3613,7 +3626,7 @@ parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
    GLint err = 0;
 
    *is_generic = 0;
-   if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
       switch (*(*inst)++) {
          case FRAGMENT_ATTRIB_COLOR:
             err = parse_color_type (ctx, inst, Program, &coord);
@@ -3792,7 +3805,7 @@ parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
    switch (*(*inst)++) {
       case FRAGMENT_RESULT_COLOR:
          /* for frag programs, this is FRAGMENT_RESULT_COLOR */
-         if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
             *binding = FRAG_OUTPUT_COLR;
             *binding_idx = 0;
          }
@@ -3804,7 +3817,7 @@ parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
 
       case FRAGMENT_RESULT_DEPTH:
          /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
-         if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
             *binding = FRAG_OUTPUT_DEPR;
             *binding_idx = 2;
          }
@@ -3987,7 +4000,7 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
             GLuint end_idx = parse_integer (inst, Program);
 
             out_of_range = 0;
-            if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+            if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
                if (((state_tokens[1] == STATE_ENV)
                     && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
                    || ((state_tokens[1] == STATE_LOCAL)
@@ -4046,10 +4059,10 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
    }
 
    /* Make sure we haven't blown past our parameter limits */
-   if (((Program->type == GL_VERTEX_PROGRAM_ARB) &&
+   if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
         (Program->Base.NumParameters >=
          ctx->Const.MaxVertexProgramLocalParams))
-       || ((Program->type == GL_FRAGMENT_PROGRAM_ARB)
+       || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
            && (Program->Base.NumParameters >=
                ctx->Const.MaxFragmentProgramLocalParams))) {
       _mesa_set_program_error (ctx, Program->Position,
@@ -4203,10 +4216,10 @@ parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
 
       temp_var->type = vt_temp;
 
-      if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
+      if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
            (Program->Base.NumTemporaries >=
             ctx->Const.MaxFragmentProgramTemps))
-          || ((Program->type == GL_VERTEX_PROGRAM_ARB)
+          || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
               && (Program->Base.NumTemporaries >=
                   ctx->Const.MaxVertexProgramTemps))) {
          _mesa_set_program_error (ctx, Program->Position,
@@ -4399,6 +4412,10 @@ parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
 /**
  * Handle the parsing out of a masked destination register
  *
+ * If we are a vertex program, make sure we don't write to
+ * result.position of we have specified that the program is
+ * position invariant
+ * 
  * \param File      - The register file we write to
  * \param Index     - The register index we write to
  * \param WriteMask - The mask controlling which components we write (1->write)
@@ -4468,6 +4485,16 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
          return 1;
    }
 
+
+   /* Position invariance test */      
+   if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
+      (*Index == 0))   {
+      _mesa_set_program_error (ctx, Program->Position,
+                  "Vertex program specified position invariance and wrote vertex position");
+      _mesa_error (ctx, GL_INVALID_OPERATION,
+                  "Vertex program specified position invariance and wrote vertex position");
+   }
+       
    /* And then the mask.
     *  w,a -> bit 0
     *  z,b -> bit 1
@@ -4476,10 +4503,10 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
     */
    mask = *(*inst)++;
 
-   WriteMask[0] = (mask & (1 << 3)) >> 3;
-   WriteMask[1] = (mask & (1 << 2)) >> 2;
-   WriteMask[2] = (mask & (1 << 1)) >> 1;
-   WriteMask[3] = (mask & (1));
+   WriteMask[0] = (GLboolean) (mask & (1 << 3)) >> 3;
+   WriteMask[1] = (GLboolean) (mask & (1 << 2)) >> 2;
+   WriteMask[2] = (GLboolean) (mask & (1 << 1)) >> 1;
+   WriteMask[3] = (GLboolean) (mask & (1));
 
    return 0;
 }
@@ -4622,16 +4649,16 @@ parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate
             mask[a] = SWIZZLE_ONE;
             break;
          case COMPONENT_X:
-            mask[a] = 0;
+            mask[a] = SWIZZLE_X;
             break;
          case COMPONENT_Y:
-            mask[a] = 1;
+            mask[a] = SWIZZLE_Y;
             break;
          case COMPONENT_Z:
-            mask[a] = 2;
+            mask[a] = SWIZZLE_Z;
             break;
          case COMPONENT_W:
-            mask[a] = 3;
+            mask[a] = SWIZZLE_W;
             break;
 
       }
@@ -5286,6 +5313,9 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
    /* The actual opcode name */
    code = *(*inst)++;
 
+   /* Record the position in the program string for debugging */
+   vp->StringPos = Program->Position;
+
    vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
 
    for (a = 0; a < 4; a++) {
@@ -5765,27 +5795,28 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
          case OPTION:
             switch (*inst++) {
                case ARB_PRECISION_HINT_FASTEST:
-                  Program->HintPrecisionFastest = 1;
+                  Program->PrecisionOption = GL_FASTEST;
                   break;
 
                case ARB_PRECISION_HINT_NICEST:
-                  Program->HintPrecisionNicest = 1;
+                  Program->PrecisionOption = GL_NICEST;
                   break;
 
                case ARB_FOG_EXP:
-                  Program->HintFogExp = 1;
+                  Program->FogOption = GL_EXP;
                   break;
 
                case ARB_FOG_EXP2:
-                  Program->HintFogExp2 = 1;
+                  Program->FogOption = GL_EXP2;
                   break;
 
                case ARB_FOG_LINEAR:
-                  Program->HintFogLinear = 1;
+                  Program->FogOption = GL_LINEAR;
                   break;
 
                case ARB_POSITION_INVARIANT:
-                  Program->HintPositionInvariant = 1;
+                  if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
+                     Program->HintPositionInvariant = 1;
                   break;
             }
             break;
@@ -5793,7 +5824,18 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
          case INSTRUCTION:
             Program->Position = parse_position (&inst);
 
-            if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+            if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
+
+               /* Check the instruction count 
+                * XXX: Does END count as an instruction?
+                */                                               
+               if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
+                  _mesa_set_program_error (ctx, Program->Position, 
+                      "Max instruction count exceeded!");
+                  _mesa_error (ctx, GL_INVALID_OPERATION,
+                      "Max instruction count exceeded!");
+               }
+                                       
                /* Realloc Program->FPInstructions */
                Program->FPInstructions =
                   (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
@@ -5806,6 +5848,16 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
                                                                     
             }
             else {
+               /* Check the instruction count 
+                * XXX: Does END count as an instruction?
+                */                                               
+               if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
+                  _mesa_set_program_error (ctx, Program->Position, 
+                      "Max instruction count exceeded!");
+                  _mesa_error (ctx, GL_INVALID_OPERATION,
+                      "Max instruction count exceeded!");
+               }
+
                /* Realloc Program->VPInstructions */
                Program->VPInstructions =
                   (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
@@ -5834,13 +5886,17 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
    }
 
    /* Finally, tag on an OPCODE_END instruction */
-   if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
       Program->FPInstructions =
          (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
                                                  Program->Base.NumInstructions*sizeof(struct fp_instruction),
                                                   (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
 
       Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
+      /* YYY Wrong Position in program, whatever, at least not random -> crash
+        Program->Position = parse_position (&inst);
+      */
+      Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
    }
    else {
       Program->VPInstructions =
@@ -5849,6 +5905,10 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
                                                   (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
 
       Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
+      /* YYY Wrong Position in program, whatever, at least not random -> crash
+        Program->Position = parse_position (&inst);
+      */
+      Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
    }
 
    /* increment Program->Base.NumInstructions */
@@ -5921,11 +5981,9 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
    program->OutputsWritten = 0;
    program->Position = 0;
    program->MajorVersion = program->MinorVersion = 0;
-   program->HintPrecisionFastest =
-   program->HintPrecisionNicest =
-   program->HintFogExp2 =
-   program->HintFogExp =
-   program->HintFogLinear = program->HintPositionInvariant = 0;
+   program->PrecisionOption = GL_DONT_CARE;
+   program->FogOption = GL_NONE;
+   program->HintPositionInvariant = GL_FALSE;
    for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
       program->TexturesUsed[a] = 0;
    program->NumAluInstructions =
@@ -5950,11 +6008,11 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
    else {
       switch (*inst++) {
          case FRAGMENT_PROGRAM:
-            program->type = GL_FRAGMENT_PROGRAM_ARB;
+            program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
             break;
 
          case VERTEX_PROGRAM:
-            program->type = GL_VERTEX_PROGRAM_ARB;
+            program->Base.Target = GL_VERTEX_PROGRAM_ARB;
             break;
       }