Merge branch 'master' of git+ssh://joukj@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / shader / arbprogparse.c
index 7d34bfbc8087df17bc174aa768bc60da6637f900..3360fef58510860fcb89eca08cf453148dcc9f8e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.3
+ * Version:  7.1
  *
  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * \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
@@ -624,6 +633,41 @@ program_error(GLcontext *ctx, GLint position, const char *descrip)
 }
 
 
+/**
+ * As above, but with an extra string parameter for more info.
+ */
+static void
+program_error2(GLcontext *ctx, GLint position, const char *descrip,
+               const char *var)
+{
+   if (descrip) {
+      const char *prefix = "glProgramString(", *suffix = ")";
+      char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
+                                        _mesa_strlen(": ") +
+                                        _mesa_strlen(var) +
+                                        _mesa_strlen(prefix) +
+                                        _mesa_strlen(suffix) + 1);
+      if (str) {
+         _mesa_sprintf(str, "%s%s: %s%s", prefix, descrip, var, suffix);
+         _mesa_error(ctx, GL_INVALID_OPERATION, str);
+         _mesa_free(str);
+      }
+   }
+   {
+      char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
+                                        _mesa_strlen(": ") +
+                                        _mesa_strlen(var) + 1);
+      if (str) {
+         _mesa_sprintf(str, "%s: %s", descrip, var);
+      }
+      _mesa_set_program_error(ctx, position, str);
+      if (str) {
+         _mesa_free(str);
+      }
+   }
+}
+
+
 
 /**
  * constructs an integer from 4 GLubytes in LE format
@@ -1217,10 +1261,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) {
@@ -1236,6 +1280,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 {
@@ -1252,6 +1299,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()");
                }
             }
          }
@@ -1274,7 +1324,7 @@ parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
          break;
 
       case STATE_POINT:
-         switch (*(*inst++)) {
+         switch (*(*inst)++) {
             case POINT_SIZE:
                state_tokens[0] = STATE_POINT_SIZE;
                break;
@@ -1678,18 +1728,14 @@ parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head
               struct arb_program *Program)
 {
    GLuint found;
-   char *error_msg;
    struct var_cache *attrib_var;
 
    attrib_var = parse_string (inst, vc_head, Program, &found);
    Program->Position = parse_position (inst);
    if (found) {
-      error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     attrib_var->name);
-      program_error(ctx, Program->Position, error_msg);
-      _mesa_free (error_msg);
+      program_error2(ctx, Program->Position,
+                     "Duplicate variable declaration",
+                     (char *) attrib_var->name);
       return 1;
    }
 
@@ -1867,12 +1913,9 @@ parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
    Program->Position = parse_position (inst);
 
    if (found) {
-      char *error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     param_var->name);
-      program_error (ctx, Program->Position, error_msg);
-      _mesa_free (error_msg);
+      program_error2(ctx, Program->Position,
+                     "Duplicate variable declaration",
+                     (char *) param_var->name);
       return 1;
    }
 
@@ -1967,12 +2010,9 @@ parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
       temp_var = parse_string (inst, vc_head, Program, &found);
       Program->Position = parse_position (inst);
       if (found) {
-         char *error_msg = (char *)
-            _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-         _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                        temp_var->name);
-         program_error(ctx, Program->Position, error_msg);
-         _mesa_free (error_msg);
+         program_error2(ctx, Program->Position,
+                        "Duplicate variable declaration",
+                        (char *) temp_var->name);
          return 1;
       }
 
@@ -2013,12 +2053,9 @@ parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head
    output_var = parse_string (inst, vc_head, Program, &found);
    Program->Position = parse_position (inst);
    if (found) {
-      char *error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     output_var->name);
-      program_error (ctx, Program->Position, error_msg);
-      _mesa_free (error_msg);
+      program_error2(ctx, Program->Position,
+                     "Duplicate variable declaration",
+                     (char *) output_var->name);
       return 1;
    }
 
@@ -2044,12 +2081,9 @@ parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
    Program->Position = parse_position (inst);
 
    if (found) {
-      char *error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     temp_var->name);
-      program_error(ctx, Program->Position, error_msg);
-      _mesa_free (error_msg);
+      program_error2(ctx, Program->Position,
+                    "Duplicate variable declaration",
+                     (char *) temp_var->name);
       return 1;
    }
 
@@ -2059,12 +2093,9 @@ parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
 
    if (!found)
    {
-      char *error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-      _mesa_sprintf (error_msg, "Alias value %s is not defined",
-                     temp_var->alias_binding->name);
-      program_error (ctx, Program->Position, error_msg);
-      _mesa_free (error_msg);
+      program_error2(ctx, Program->Position,
+                     "Undefined alias value",
+                     (char *) temp_var->alias_binding->name);
       return 1;
    }
 
@@ -2087,12 +2118,9 @@ parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_hea
       temp_var = parse_string (inst, vc_head, Program, &found);
       Program->Position = parse_position (inst);
       if (found) {
-         char *error_msg = (char *)
-            _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-         _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                        temp_var->name);
-         program_error (ctx, Program->Position, error_msg);
-         _mesa_free (error_msg);
+         program_error2(ctx, Program->Position,
+                        "Duplicate variable declaration",
+                        (char *) temp_var->name);
          return 1;
       }
 
@@ -2445,8 +2473,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 */
+                  program_error2(ctx, Program->Position,
+                                 "Undefined variable",
+                                 (char *) src->name);
                   return 1;
                }
 
@@ -2653,6 +2682,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);
 
@@ -2970,27 +3000,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) {
@@ -2998,6 +3055,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:
@@ -3464,6 +3524,10 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst,
                      /* do nothing for now */
                   }
                   break;
+
+               case MESA_TEXTURE_ARRAY:
+                 /* do nothing for now */
+                  break;
             }
             break;
 
@@ -3529,7 +3593,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"
 ;
 
 
@@ -3584,10 +3648,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;
@@ -3603,7 +3667,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");
@@ -3782,6 +3848,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;
@@ -3862,7 +3929,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);