Fix state.texgen parsing error (bug 12313).
[mesa.git] / src / mesa / shader / arbprogparse.c
index 43e2c7e1becef54ac1974c381afc5700c653f69a..737194d3b65e71ef6fa2446d4e7e740865d59597 100644 (file)
  * \author Karl Rasche
  */
 
-#include "glheader.h"
-#include "imports.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "shader/grammar/grammar_mesa.h"
 #include "arbprogparse.h"
-#include "grammar_mesa.h"
 #include "program.h"
 #include "prog_parameter.h"
 #include "prog_statevars.h"
@@ -71,6 +71,7 @@ struct arb_program
 
    /* ARB_fragment_program specifics */
    GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; 
+   GLbitfield ShadowSamplers;
    GLuint NumAluInstructions; 
    GLuint NumTexInstructions;
    GLuint NumTexIndirections;
@@ -181,7 +182,7 @@ LONGSTRING static char arb_grammar_text[] =
     - changed and merged V_* and F_* opcode values to OP_*.
     - added GL_ARB_fragment_program_shadow specific tokens (michal)
 */
-#define  REVISION                                   0x09
+#define  REVISION                                   0x0a
 
 /* program type */
 #define  FRAGMENT_PROGRAM                           0x01
@@ -209,6 +210,9 @@ LONGSTRING static char arb_grammar_text[] =
 /* GL_ARB_draw_buffers option */
 #define  ARB_DRAW_BUFFERS                           0x07
 
+/* GL_MESA_texture_array option */
+#define  MESA_TEXTURE_ARRAY                        0x08
+
 /* GL_ARB_fragment_program instruction class */
 #define  OP_ALU_INST                                0x00
 #define  OP_TEX_INST                                0x01
@@ -368,6 +372,11 @@ LONGSTRING static char arb_grammar_text[] =
 #define  TEXTARGET_SHADOW1D                         0x06
 #define  TEXTARGET_SHADOW2D                         0x07
 #define  TEXTARGET_SHADOWRECT                       0x08
+/* GL_MESA_texture_array */
+#define  TEXTARGET_1D_ARRAY                         0x09
+#define  TEXTARGET_2D_ARRAY                         0x0a
+#define  TEXTARGET_SHADOW1D_ARRAY                   0x0b
+#define  TEXTARGET_SHADOW2D_ARRAY                   0x0c
 
 /* face type */
 #define  FACE_FRONT                                 0x00
@@ -1085,7 +1094,8 @@ parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Progra
  */
 static GLuint
 parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
-                         struct arb_program *Program, GLint * state_tokens)
+                         struct arb_program *Program,
+                         gl_state_index state_tokens[STATE_LENGTH])
 {
    switch (*(*inst)++) {
       case STATE_MATERIAL_PARSER:
@@ -1187,12 +1197,10 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
       case STATE_FOG:
          switch (*(*inst)++) {
             case FOG_COLOR:
-               state_tokens[0] = STATE_FOG;
-               state_tokens[1] = STATE_FOG_COLOR;
+               state_tokens[0] = STATE_FOG_COLOR;
                break;
             case FOG_PARAMS:
-               state_tokens[0] = STATE_FOG;
-               state_tokens[1] = STATE_FOG_PARAMS;
+               state_tokens[0] = STATE_FOG_PARAMS;
                break;
          }
          break;
@@ -1218,10 +1226,10 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
            state_tokens[1] = coord;
 
             /* EYE or OBJECT */
-            type = *(*inst++);
+            type = *(*inst)++;
 
             /* 0 - s, 1 - t, 2 - r, 3 - q */
-            coord = *(*inst++);
+            coord = *(*inst)++;
 
             if (type == TEX_GEN_EYE) {
                switch (coord) {
@@ -1237,6 +1245,9 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
                   case COMPONENT_W:
                      state_tokens[2] = STATE_TEXGEN_EYE_Q;
                      break;
+                  default:
+                     _mesa_problem(ctx, "bad texgen component in "
+                                   "parse_state_single_item()");
                }
             }
             else {
@@ -1253,6 +1264,9 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
                   case COMPONENT_W:
                      state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
                      break;
+                  default:
+                     _mesa_problem(ctx, "bad texgen component in "
+                                   "parse_state_single_item()");
                }
             }
          }
@@ -1269,12 +1283,13 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
       case STATE_CLIP_PLANE:
          state_tokens[0] = STATE_CLIPPLANE;
          state_tokens[1] = parse_integer (inst, Program);
-         if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
+         if (parse_clipplane_num (ctx, inst, Program,
+                                  (GLint *) &state_tokens[1]))
             return 1;
          break;
 
       case STATE_POINT:
-         switch (*(*inst++)) {
+         switch (*(*inst)++) {
             case POINT_SIZE:
                state_tokens[0] = STATE_POINT_SIZE;
                break;
@@ -1287,9 +1302,10 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
 
          /* XXX: I think this is the correct format for a matrix row */
       case STATE_MATRIX_ROWS:
-         if (parse_matrix
-             (ctx, inst, Program, &state_tokens[0], &state_tokens[1],
-              &state_tokens[4]))
+         if (parse_matrix(ctx, inst, Program,
+                          (GLint *) &state_tokens[0],
+                          (GLint *) &state_tokens[1],
+                          (GLint *) &state_tokens[4]))
             return 1;
 
          state_tokens[2] = parse_integer (inst, Program);       /* The first row to grab */
@@ -1345,7 +1361,8 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
  */
 static GLuint
 parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
-                           struct arb_program *Program, GLint * state_tokens)
+                           struct arb_program *Program,
+                           gl_state_index state_tokens[STATE_LENGTH])
 {
    if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
       state_tokens[0] = STATE_FRAGMENT_PROGRAM;
@@ -1720,7 +1737,7 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
 {
    GLint idx;
    GLuint err = 0;
-   GLint state_tokens[STATE_LENGTH];
+   gl_state_index state_tokens[STATE_LENGTH];
    GLfloat const_values[4];
 
    switch (*(*inst)++) {
@@ -2443,8 +2460,9 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
                Program->Position = parse_position (inst);
 
                if (!found) {
-                  program_error(ctx, Program->Position,
-                                "2: Undefined variable"); /* src->name */
+                  char s[1000];
+                  sprintf(s, "Undefined variable: %s", src->name);
+                  program_error(ctx, Program->Position, s);
                   return 1;
                }
 
@@ -2651,6 +2669,7 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
    GLuint texcoord;
    GLubyte instClass, type, code;
    GLboolean rel;
+   GLuint shadow_tex = 0;
 
    _mesa_init_instructions(fp, 1);
 
@@ -2968,27 +2987,54 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
 
          /* texTarget */
          switch (*(*inst)++) {
+            case TEXTARGET_SHADOW1D:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
             case TEXTARGET_1D:
                fp->TexSrcTarget = TEXTURE_1D_INDEX;
                break;
+            case TEXTARGET_SHADOW2D:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
             case TEXTARGET_2D:
                fp->TexSrcTarget = TEXTURE_2D_INDEX;
                break;
             case TEXTARGET_3D:
                fp->TexSrcTarget = TEXTURE_3D_INDEX;
                break;
+            case TEXTARGET_SHADOWRECT:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
             case TEXTARGET_RECT:
                fp->TexSrcTarget = TEXTURE_RECT_INDEX;
                break;
             case TEXTARGET_CUBE:
                fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
                break;
-           case TEXTARGET_SHADOW1D:
-           case TEXTARGET_SHADOW2D:
-           case TEXTARGET_SHADOWRECT:
-              /* TODO ARB_fragment_program_shadow code */
-              break;
+            case TEXTARGET_SHADOW1D_ARRAY:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
+            case TEXTARGET_1D_ARRAY:
+               fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
+               break;
+            case TEXTARGET_SHADOW2D_ARRAY:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
+            case TEXTARGET_2D_ARRAY:
+               fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
+               break;
          }
+
+         /* Don't test the first time a particular sampler is seen.  Each time
+          * after that, make sure the shadow state is the same.
+          */
+         if ((_mesa_bitcount(Program->TexturesUsed[texcoord]) > 0)
+             && ((Program->ShadowSamplers & (1 << texcoord)) != shadow_tex)) {
+            program_error(ctx, Program->Position,
+                          "texture image unit used for shadow sampling and non-shadow sampling");
+            return 1;
+         }
+
          Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
          /* Check that both "2D" and "CUBE" (for example) aren't both used */
          if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
@@ -2996,6 +3042,9 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
                           "multiple targets used on one texture image unit");
             return 1;
          }
+      
+
+         Program->ShadowSamplers |= shadow_tex;
          break;
 
       case OP_TEX_KIL:
@@ -3462,6 +3511,10 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst,
                      /* do nothing for now */
                   }
                   break;
+
+               case MESA_TEXTURE_ARRAY:
+                 /* do nothing for now */
+                  break;
             }
             break;
 
@@ -3527,7 +3580,7 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst,
 
 /* XXX temporary */
 LONGSTRING static char core_grammar_text[] =
-#include "grammar_syn.h"
+#include "shader/grammar/grammar_syn.h"
 ;
 
 
@@ -3582,10 +3635,10 @@ enable_parser_extensions(GLcontext *ctx, grammar id)
    if (ctx->Extensions.ARB_matrix_palette
        && !enable_ext(ctx, id, "matrix_palette"))
       return GL_FALSE;
+#endif
    if (ctx->Extensions.ARB_fragment_program_shadow
        && !enable_ext(ctx, id, "fragment_program_shadow"))
       return GL_FALSE;
-#endif
    if (ctx->Extensions.EXT_point_parameters
        && !enable_ext(ctx, id, "point_parameters"))
       return GL_FALSE;
@@ -3601,7 +3654,9 @@ enable_parser_extensions(GLcontext *ctx, grammar id)
    if (ctx->Extensions.ARB_draw_buffers
        && !enable_ext(ctx, id, "draw_buffers"))
       return GL_FALSE;
-
+   if (ctx->Extensions.MESA_texture_array
+       && !enable_ext(ctx, id, "texture_array"))
+      return GL_FALSE;
 #if 1
    /* hack for Warcraft (see bug 8060) */
    enable_ext(ctx, id, "vertex_blend");
@@ -3780,6 +3835,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
    program->HintPositionInvariant = GL_FALSE;
    for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
       program->TexturesUsed[a] = 0x0;
+   program->ShadowSamplers = 0x0;
    program->NumAluInstructions =
    program->NumTexInstructions =
    program->NumTexIndirections = 0;
@@ -3860,7 +3916,9 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
    program->Base.OutputsWritten  = ap.Base.OutputsWritten;
    for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
       program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
+   program->Base.ShadowSamplers = ap.ShadowSamplers;
    program->FogOption          = ap.FogOption;
+   program->UsesKill          = ap.UsesKill;
 
    if (program->Base.Instructions)
       _mesa_free(program->Base.Instructions);