Clean-up of parser error handling/reporting.
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 14 Mar 2003 15:40:59 +0000 (15:40 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 14 Mar 2003 15:40:59 +0000 (15:40 +0000)
Basic fragment program texture instructions are limping along.

src/mesa/main/nvfragparse.c
src/mesa/main/nvfragprog.h
src/mesa/main/nvprogram.c
src/mesa/main/nvvertparse.c
src/mesa/swrast/s_context.c
src/mesa/swrast/s_nvfragprog.c
src/mesa/swrast/s_triangle.c

index f7eda38cc423620242a93d51c60573879566e77f..60b15bcd06e291567d044b239ebc700bc9d5c6b1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nvfragparse.c,v 1.12 2003/03/01 01:50:22 brianp Exp $ */
+/* $Id: nvfragparse.c,v 1.13 2003/03/14 15:40:59 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
 #define OUTPUT_NONE 22
 
 /* Optional suffixes */
-#define _R  0x01  /* real */
-#define _H  0x02  /* half */
-#define _X  0x04  /* fixed */
-#define _C  0x08  /* set cond codes */
-#define _S  0x10  /* saturate */
-
-#define SINGLE  _R
-#define HALF    _H
-#define FIXED   _X
+#define _R  FLOAT32  /* float */
+#define _H  FLOAT16  /* half-float */
+#define _X  FIXED12  /* fixed */
+#define _C  0x08     /* set cond codes */
+#define _S  0x10     /* saturate, clamp result to [0,1] */
 
 struct instruction_pattern {
    const char *name;
@@ -138,16 +134,73 @@ static const struct instruction_pattern Instructions[] = {
 };
 
 
-
+/*
+ * Information needed or computed during parsing.
+ * Remember, we can't modify the target program object until we've
+ * _successfully_ parsed the program text.
+ */
 struct parse_state {
+   GLcontext *ctx;
+   const GLubyte *start;              /* start of program string */
    const GLubyte *pos;                /* current position */
    struct fragment_program *program;  /* current program */
    GLuint numInst;                    /* number of instructions parsed */
    GLuint inputsRead;                 /* bitmask of input registers used */
    GLuint outputsWritten;             /* 2 = depth register */
+   GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];
 };
 
 
+/*
+ * Called whenever we find an error during parsing.
+ */
+static void
+record_error(struct parse_state *parseState, const char *msg, int lineNo)
+{
+#ifdef DEBUG
+   GLint line, column;
+   const GLubyte *lineStr;
+   lineStr = _mesa_find_line_column(parseState->start,
+                                    parseState->pos, &line, &column);
+   _mesa_debug(parseState->ctx,
+               "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
+               lineNo, line, column, (char *) lineStr, msg);
+   _mesa_free((void *) lineStr);
+#else
+   (void) lineNo;
+#endif
+
+   /* Check that no error was already recorded.  Only record the first one. */
+   if (parseState->ctx->Program.ErrorString[0] == 0) {
+      _mesa_set_program_error(parseState->ctx,
+                              parseState->pos - parseState->start,
+                              msg);
+   }
+}
+
+
+#define RETURN_ERROR                                                   \
+do {                                                                   \
+   record_error(parseState, "Unexpected end of input.", __LINE__);     \
+   return GL_FALSE;                                                    \
+} while(0)
+
+#define RETURN_ERROR1(msg)                                             \
+do {                                                                   \
+   record_error(parseState, msg, __LINE__);                            \
+   return GL_FALSE;                                                    \
+} while(0)
+
+#define RETURN_ERROR2(msg1, msg2)                                      \
+do {                                                                   \
+   char err[1000];                                                     \
+   _mesa_sprintf(err, "%s %s", msg1, msg2);                            \
+   record_error(parseState, err, __LINE__);                            \
+   return GL_FALSE;                                                    \
+} while(0)
+
+
+
 
 /*
  * Search a list of instruction structures for a match.
@@ -331,35 +384,6 @@ static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = {
 };
 
 
-#ifdef DEBUG
-
-#define RETURN_ERROR                                           \
-do {                                                           \
-   _mesa_printf("nvfragparse.c error at %d: parse error\n", __LINE__); \
-   return GL_FALSE;                                            \
-} while(0)
-
-#define RETURN_ERROR1(msg)                                     \
-do {                                                           \
-   _mesa_printf("nvfragparse.c error at %d: %s\n", __LINE__, msg);     \
-   return GL_FALSE;                                            \
-} while(0)
-
-#define RETURN_ERROR2(msg1, msg2)                                      \
-do {                                                                   \
-   _mesa_printf("nvfragparse.c error at %d: %s %s\n", __LINE__, msg1, msg2);\
-   return GL_FALSE;                                                    \
-} while(0)
-
-#else
-
-#define RETURN_ERROR                return GL_FALSE
-#define RETURN_ERROR1(msg1)         return GL_FALSE
-#define RETURN_ERROR2(msg1, msg2)   return GL_FALSE
-
-#endif
-
-
 static GLint
 TempRegisterNumber(GLuint r)
 {
@@ -576,7 +600,7 @@ Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
  */
 static GLboolean
 Parse_TextureImageId(struct parse_state *parseState,
-                     GLuint *texUnit, GLuint *texTargetIndex)
+                     GLubyte *texUnit, GLubyte *texTargetBit)
 {
    GLubyte imageSrc[100];
    GLint unit;
@@ -600,27 +624,27 @@ Parse_TextureImageId(struct parse_state *parseState,
       RETURN_ERROR1("Expected ,");
 
    if (Parse_String(parseState, "1D")) {
-      *texTargetIndex = TEXTURE_1D_INDEX;
+      *texTargetBit = TEXTURE_1D_BIT;
    }
    else if (Parse_String(parseState, "2D")) {
-      *texTargetIndex = TEXTURE_2D_INDEX;
+      *texTargetBit = TEXTURE_2D_BIT;
    }
    else if (Parse_String(parseState, "3D")) {
-      *texTargetIndex = TEXTURE_3D_INDEX;
+      *texTargetBit = TEXTURE_3D_BIT;
    }
    else if (Parse_String(parseState, "CUBE")) {
-      *texTargetIndex = TEXTURE_CUBE_INDEX;
+      *texTargetBit = TEXTURE_CUBE_BIT;
    }
    else if (Parse_String(parseState, "RECT")) {
-      *texTargetIndex = TEXTURE_RECT_INDEX;
+      *texTargetBit = TEXTURE_RECT_BIT;
    }
    else {
       RETURN_ERROR1("Invalid texture target token");
    }
 
    /* update record of referenced texture units */
-   parseState->program->TexturesUsed[*texUnit] |= (1 << *texTargetIndex);
-   if (_mesa_bitcount(parseState->program->TexturesUsed[*texUnit]) > 1) {
+   parseState->texturesUsed[*texUnit] |= *texTargetBit;
+   if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
       RETURN_ERROR1("Only one texture target can be used per texture unit.");
    }
 
@@ -700,7 +724,7 @@ Parse_CondCodeMask(struct parse_state *parseState,
          RETURN_ERROR;
 
       if (!Parse_SwizzleSuffix(token, dstReg->CondSwizzle))
-         RETURN_ERROR1("Bad swizzle suffix");
+         RETURN_ERROR1("Invalid swizzle suffix");
    }
 
    return GL_TRUE;
@@ -726,11 +750,11 @@ Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
       if (token[0] == 'H')
          reg += 32;
       if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
-         RETURN_ERROR1("Bad temporary register name");
+         RETURN_ERROR1("Invalid temporary register name");
       *tempRegNum = FP_TEMP_REG_START + reg;
    }
    else {
-      RETURN_ERROR1("Bad temporary register name");
+      RETURN_ERROR1("Invalid temporary register name");
    }
 
    return GL_TRUE;
@@ -750,7 +774,7 @@ Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
        *regNum = FP_DUMMY_REG_START + 1;
    }
    else {
-      RETURN_ERROR1("Bad write-only register name");
+      RETURN_ERROR1("Invalid write-only register name");
    }
 
    return GL_TRUE;
@@ -775,7 +799,7 @@ Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
       /* a numbered program parameter register */
       GLint reg = _mesa_atoi((const char *) token);
       if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
-         RETURN_ERROR1("Bad constant program number");
+         RETURN_ERROR1("Invalid constant program number");
       *regNum = FP_PROG_REG_START + reg;
    }
    else {
@@ -815,7 +839,7 @@ Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
    }
    if (!InputRegisters[j]) {
       /* unknown input register label */
-      RETURN_ERROR2("Bad register name", token);
+      RETURN_ERROR2("Invalid register name", token);
    }
 
    /* Match '[' */
@@ -852,7 +876,7 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
       }
    }
    if (!OutputRegisters[j])
-      RETURN_ERROR1("Unrecognized output register name");
+      RETURN_ERROR1("Invalid output register name");
 
    /* Match ']' */
    if (!Parse_String(parseState, "]"))
@@ -889,7 +913,7 @@ Parse_MaskedDstReg(struct parse_state *parseState,
          RETURN_ERROR;
    }
    else {
-      RETURN_ERROR1("Bad destination register name");
+      RETURN_ERROR1("Invalid destination register name");
    }
 
    /* Parse optional write mask */
@@ -922,7 +946,7 @@ Parse_MaskedDstReg(struct parse_state *parseState,
          k++;
       }
       if (k == 0) {
-         RETURN_ERROR1("Bad writemask character");
+         RETURN_ERROR1("Invalid writemask character");
       }
 
    }
@@ -1039,7 +1063,7 @@ Parse_VectorSrc(struct parse_state *parseState,
       srcReg->Register = 0; /* XXX fix */
    }
    else {
-      RETURN_ERROR2("Bad source register name", token);
+      RETURN_ERROR2("Invalid source register name", token);
    }
 
    /* init swizzle fields */
@@ -1054,7 +1078,7 @@ Parse_VectorSrc(struct parse_state *parseState,
          RETURN_ERROR;
 
       if (!Parse_SwizzleSuffix(token, srcReg->Swizzle))
-         RETURN_ERROR1("Bad swizzle suffix");
+         RETURN_ERROR1("Invalid swizzle suffix");
    }
 
    /* Finish absolute value */
@@ -1093,7 +1117,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
          RETURN_ERROR;
    }
    else {
-      RETURN_ERROR2("Bad source register name", token);
+      RETURN_ERROR2("Invalid source register name", token);
    }
 
    /* Look for .[xyzw] suffix */
@@ -1116,7 +1140,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
       srcReg->Swizzle[0] = 3;
    }
    else {
-      RETURN_ERROR1("Bad scalar source suffix");
+      RETURN_ERROR1("Invalid scalar source suffix");
    }
    srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
 
@@ -1178,21 +1202,26 @@ Parse_InstructionSequence(struct parse_state *parseState,
          _mesa_add_symbol(&(parseState->program->SymbolTable),
                           (const char *) id, Declaration, value);
       }
+      else if (Parse_String(parseState, "END")) {
+         inst->Opcode = FP_OPCODE_END;
+         parseState->numInst++;
+         if (Parse_Token(parseState, token)) {
+            RETURN_ERROR1("Code after END opcode.");
+         }
+         break;
+      }
       else {
          /* general/arithmetic instruction */
 
          /* get token */
          if (!Parse_Token(parseState, token)) {
-            inst->Opcode = FP_OPCODE_END;
-            parseState->numInst++;
-            break;
+            RETURN_ERROR1("Missing END instruction.");
          }
 
          /* try to find matching instuction */
          instMatch = MatchInstruction(token);
          if (instMatch.opcode < 0) {
             /* bad instruction name */
-            printf("-------- errror\n");
             RETURN_ERROR2("Unexpected token: ", token);
          }
 
@@ -1262,7 +1291,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
             if (!Parse_String(parseState, ","))
                RETURN_ERROR1("Expected ,");
             if (!Parse_TextureImageId(parseState, &inst->TexSrcUnit,
-                                      &inst->TexSrcIndex))
+                                      &inst->TexSrcBit))
                RETURN_ERROR;
          }
          else if (instMatch.inputs == INPUT_3V_T) {
@@ -1279,7 +1308,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
             if (!Parse_String(parseState, ","))
                RETURN_ERROR1("Expected ,");
             if (!Parse_TextureImageId(parseState, &inst->TexSrcUnit,
-                                      &inst->TexSrcIndex))
+                                      &inst->TexSrcBit))
                RETURN_ERROR;
          }
 
@@ -1324,9 +1353,15 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
    programString[len] = 0;
 
    /* Get ready to parse */
+   _mesa_bzero(&parseState, sizeof(struct parse_state));
+   parseState.ctx = ctx;
+   parseState.start = programString;
    parseState.program = program;
    parseState.numInst = 0;
 
+   /* Reset error state */
+   _mesa_set_program_error(ctx, -1, NULL);
+
    /* check the program header */
    if (_mesa_strncmp((const char *) programString, "!!FP1.0", 7) == 0) {
       target = GL_FRAGMENT_PROGRAM_NV;
@@ -1354,7 +1389,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
    }
 
    if (Parse_InstructionSequence(&parseState, instBuffer)) {
-      /* success! */
+      GLuint u;
+      /* successful parse! */
 
       if (parseState.outputsWritten == 0) {
          /* must write at least one output! */
@@ -1386,6 +1422,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
       program->Instructions = newInst;
       program->InputsRead = parseState.inputsRead;
       program->OutputsWritten = parseState.outputsWritten;
+      for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
+         program->TexturesUsed[u] = parseState.texturesUsed[u];
 
       /* allocate registers for declared program parameters */
       _mesa_assign_program_registers(&(program->SymbolTable));
@@ -1399,18 +1437,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
    else {
       /* Error! */
       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
-      ctx->Program.ErrorPos = (GLubyte *) parseState.pos - programString;
-#ifdef DEBUG
-      {
-         GLint line, column;
-         const GLubyte *lineStr;
-         lineStr = _mesa_find_line_column(programString,
-                                          parseState.pos, &line, &column);
-         _mesa_debug(ctx, "Parse error on line %d, column %d:%s\n",
-                     line, column, (char *) lineStr);
-         _mesa_free((void *) lineStr);
-      }
-#endif
+      /* NOTE: _mesa_set_program_error would have been called already */
    }
 }
 
@@ -1449,7 +1476,7 @@ PrintSrcReg(const struct fp_src_register *src)
       _mesa_printf("%cC", "HR"[r]);
    }
    else {
-      _mesa_problem(NULL, "Bad fragment register %d", src->Register);
+      _mesa_problem(NULL, "Invalid fragment register %d", src->Register);
       return;
    }
    if (src->Swizzle[0] == src->Swizzle[1] &&
@@ -1476,24 +1503,24 @@ static void
 PrintTextureSrc(const struct fp_instruction *inst)
 {
    _mesa_printf("TEX%d, ", inst->TexSrcUnit);
-   switch (inst->TexSrcIndex) {
-   case TEXTURE_1D_INDEX:
+   switch (inst->TexSrcBit) {
+   case TEXTURE_1D_BIT:
       _mesa_printf("1D");
       break;
-   case TEXTURE_2D_INDEX:
+   case TEXTURE_2D_BIT:
       _mesa_printf("2D");
       break;
-   case TEXTURE_3D_INDEX:
+   case TEXTURE_3D_BIT:
       _mesa_printf("3D");
       break;
-   case TEXTURE_RECT_INDEX:
+   case TEXTURE_RECT_BIT:
       _mesa_printf("RECT");
       break;
-   case TEXTURE_CUBE_INDEX:
+   case TEXTURE_CUBE_BIT:
       _mesa_printf("CUBE");
       break;
    default:
-      _mesa_problem(NULL, "Bad textue target in PrintTextureSrc");
+      _mesa_problem(NULL, "Invalid textue target in PrintTextureSrc");
    }
 }
 
@@ -1588,9 +1615,9 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
          if (inst->Opcode == Instructions[i].opcode) {
             /* print instruction name */
             _mesa_printf("%s", Instructions[i].name);
-            if (inst->Precision == HALF)
+            if (inst->Precision == FLOAT16)
                _mesa_printf("H");
-            else if (inst->Precision == FIXED)
+            else if (inst->Precision == FIXED12)
                _mesa_printf("X");
             if (inst->UpdateCondRegister)
                _mesa_printf("C");
@@ -1645,7 +1672,8 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
          }
       }
       if (!Instructions[i].name) {
-         _mesa_printf("Bad opcode %d\n", inst->Opcode);
+         _mesa_printf("Invalid opcode %d\n", inst->Opcode);
       }
    }
+   _mesa_printf("END\n");
 }
index d7ef8d42485242531d55662c6c996bae523567ac..d7e23627a424d6d93228b38da3b72862b4a9887f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nvfragprog.h,v 1.3 2003/02/23 04:09:21 brianp Exp $ */
+/* $Id: nvfragprog.h,v 1.4 2003/03/14 15:40:59 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -49,7 +49,7 @@
 #define FP_DUMMY_REG_END    (FP_DUMMY_REG_START + MAX_NV_FRAGMENT_PROGRAM_WRITE_ONLYS - 1)
 
 
-
+/* condition codes */
 #define COND_GT  1  /* greater than zero */
 #define COND_EQ  2  /* equal to zero */
 #define COND_LT  3  /* less than zero */
 #define COND_FL  9  /* always false */
 
 
+/* instruction precision */
+#define FLOAT32  0x1
+#define FLOAT16  0x2
+#define FIXED12  0x4
+
+
 enum fp_opcode {
    FP_OPCODE_ADD = 1000,
    FP_OPCODE_COS,
@@ -139,9 +145,9 @@ struct fp_instruction
    struct fp_dst_register DstReg;
    GLboolean Saturate;
    GLboolean UpdateCondRegister;
-   GLuint Precision;    /* SINGLE, HALF or FIXED */
-   GLuint TexSrcUnit;   /* texture unit for TEX, TXD, TXP instructions */
-   GLuint TexSrcIndex;  /* texture target for TEX, TXD, TXP instructions */
+   GLubyte Precision;    /* FLOAT32, FLOAT16 or FIXED12 */
+   GLubyte TexSrcUnit;   /* texture unit for TEX, TXD, TXP instructions */
+   GLubyte TexSrcBit;    /* TEXTURE_1D,2D,3D,CUBE,RECT_BIT source target */
 };
 
 
index 1e255ba02887096246063586e8224e45f0a2d402..4e371620c5735113d90eea0c2a54df3a17ce691b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nvprogram.c,v 1.7 2003/03/10 00:26:24 brianp Exp $ */
+/* $Id: nvprogram.c,v 1.8 2003/03/14 15:40:59 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -260,35 +260,41 @@ _mesa_BindProgramNV(GLenum target, GLuint id)
    /* NOTE: binding to a non-existant program is not an error.
     * That's supposed to be caught in glBegin.
     */
-   prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-
-   if (!prog && id > 0){
-      /* allocate new program */
-      if (target == GL_VERTEX_PROGRAM_NV) {
-         struct vertex_program *vprog = CALLOC_STRUCT(vertex_program);
-         if (!vprog) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
-            return;
+   if (id == 0) {
+      /* OK, the null program object */
+      prog = NULL;
+   }
+   else {
+      prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
+
+      if (!prog && id > 0){
+         /* allocate new program */
+         if (target == GL_VERTEX_PROGRAM_NV) {
+            struct vertex_program *vprog = CALLOC_STRUCT(vertex_program);
+            if (!vprog) {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
+               return;
+            }
+            prog = &(vprog->Base);
          }
-         prog = &(vprog->Base);
-      }
-      else if (target == GL_FRAGMENT_PROGRAM_NV) {
-         struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
-         if (!fprog) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
+         else if (target == GL_FRAGMENT_PROGRAM_NV) {
+            struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
+            if (!fprog) {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
+               return;
+            }
+            prog = &(fprog->Base);
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV(target)");
             return;
          }
-         prog = &(fprog->Base);
+         prog->Id = id;
+         prog->Target = target;
+         prog->Resident = GL_TRUE;
+         prog->RefCount = 1;
+         _mesa_HashInsert(ctx->Shared->Programs, id, prog);
       }
-      else {
-         _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV(target)");
-         return;
-      }
-      prog->Id = id;
-      prog->Target = target;
-      prog->Resident = GL_TRUE;
-      prog->RefCount = 1;
-      _mesa_HashInsert(ctx->Shared->Programs, id, prog);
    }
 
    /* bind now */
index 83215cb621a938c7344addc0f990fac7e84c30c3..a84eb34071e1a8b56f25fd4fb0e15489ee44e5a6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nvvertparse.c,v 1.3 2003/02/25 19:27:54 brianp Exp $ */
+/* $Id: nvvertparse.c,v 1.4 2003/03/14 15:40:59 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -47,6 +47,8 @@
  * program attributes.
  */
 struct parse_state {
+   GLcontext *ctx;
+   const GLubyte *start;
    const GLubyte *pos;
    GLboolean isStateProgram;
    GLboolean isPositionInvariant;
@@ -58,6 +60,58 @@ struct parse_state {
 };
 
 
+/*
+ * Called whenever we find an error during parsing.
+ */
+static void
+record_error(struct parse_state *parseState, const char *msg, int lineNo)
+{
+#ifdef DEBUG
+   GLint line, column;
+   const GLubyte *lineStr;
+   lineStr = _mesa_find_line_column(parseState->start,
+                                    parseState->pos, &line, &column);
+   _mesa_debug(parseState->ctx,
+               "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
+               lineNo, line, column, (char *) lineStr, msg);
+   _mesa_free((void *) lineStr);
+#else
+   (void) lineNo;
+#endif
+
+   /* Check that no error was already recorded.  Only record the first one. */
+   if (parseState->ctx->Program.ErrorString[0] == 0) {
+      _mesa_set_program_error(parseState->ctx,
+                              parseState->pos - parseState->start,
+                              msg);
+   }
+}
+
+
+#define RETURN_ERROR                                                   \
+do {                                                                   \
+   record_error(parseState, "Unexpected end of input.", __LINE__);     \
+   return GL_FALSE;                                                    \
+} while(0)
+
+#define RETURN_ERROR1(msg)                                             \
+do {                                                                   \
+   record_error(parseState, msg, __LINE__);                            \
+   return GL_FALSE;                                                    \
+} while(0)
+
+#define RETURN_ERROR2(msg1, msg2)                                      \
+do {                                                                   \
+   char err[1000];                                                     \
+   _mesa_sprintf(err, "%s %s", msg1, msg2);                            \
+   record_error(parseState, err, __LINE__);                            \
+   return GL_FALSE;                                                    \
+} while(0)
+
+
+
+
+
 static GLboolean IsLetter(GLubyte b)
 {
    return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
@@ -227,34 +281,6 @@ static const char *Opcodes[] = {
 };
 
 
-#ifdef DEBUG
-
-#define RETURN_ERROR                                           \
-do {                                                           \
-   _mesa_printf("vert prog error at %d\n", __LINE__);          \
-   return GL_FALSE;                                            \
-} while(0)
-
-#define RETURN_ERROR1(msg)                                     \
-do {                                                           \
-   _mesa_printf("vert prog error at %d: %s\n", __LINE__, msg); \
-   return GL_FALSE;                                            \
-} while(0)
-
-#define RETURN_ERROR2(msg1, msg2)                                      \
-do {                                                                   \
-   _mesa_printf("vert prog error at %d: %s %s\n", __LINE__, msg1, msg2);\
-   return GL_FALSE;                                                    \
-} while(0)
-
-#else
-
-#define RETURN_ERROR                return GL_FALSE
-#define RETURN_ERROR1(msg1)         return GL_FALSE
-#define RETURN_ERROR2(msg1, msg2)   return GL_FALSE
-
-#endif
-
 
 static GLuint
 IsProgRegister(GLuint r)
@@ -1174,7 +1200,9 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
    MEMCPY(programString, str, len);
    programString[len] = 0;
 
-   /* get ready to parse */
+   /* Get ready to parse */
+   parseState.ctx = ctx;
+   parseState.start = programString;
    parseState.isPositionInvariant = GL_FALSE;
    parseState.isVersion1_1 = GL_FALSE;
    parseState.numInst = 0;
@@ -1182,6 +1210,9 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
    parseState.outputsWritten = 0;
    parseState.progRegsWritten = 0;
 
+   /* Reset error state */
+   _mesa_set_program_error(ctx, -1, NULL);
+
    /* check the program header */
    if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
       target = GL_VERTEX_PROGRAM_NV;
@@ -1268,19 +1299,12 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
    }
    else {
       /* Error! */
-      ctx->Program.ErrorPos = parseState.pos - str;
       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
-#ifdef DEBUG
-      {
-         GLint line, column;
-         const GLubyte *lineStr;
-         lineStr = _mesa_find_line_column(programString,
-                                          parseState.pos, &line, &column);
-         _mesa_debug(ctx, "Parse error on line %d, column %d:%s\n",
-                     line, column, (char *) lineStr);
-         _mesa_free((void *) lineStr);
-      }
-#endif
+      /* NOTE: _mesa_set_program_error would have been called already */
+      /* GL_NV_vertex_program isn't supposed to set the error string
+       * so we reset it here.
+       */
+      _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
    }
 }
 
index 2c3ffbedd777df76255161ef1d526c5d2db09768..6ed0c42e4d6a3b8019746611105b32dc77462cc5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_context.c,v 1.45 2003/02/23 04:10:54 brianp Exp $ */
+/* $Id: s_context.c,v 1.46 2003/03/14 15:41:00 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
  *
  * Authors:
  *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Brian Paul
  */
 
-#include "glheader.h"
+#include "imports.h"
 #include "context.h"
 #include "mtypes.h"
-#include "imports.h"
+#include "texobj.h"
 
 #include "swrast.h"
 #include "s_blend.h"
@@ -305,11 +306,40 @@ _swrast_validate_texture_sample( GLcontext *ctx, GLuint texUnit,
       }
    }
 
+   if (ctx->FragmentProgram.Enabled) {
+      ASSERT(ctx->FragmentProgram.Current);
+      /* only one target can be referenced per unit per fragment program */
+      switch (ctx->FragmentProgram.Current->TexturesUsed[texUnit]) {
+      case TEXTURE_1D_BIT:
+         tObj = ctx->Texture.Unit[texUnit].Current1D;
+         break;
+      case TEXTURE_2D_BIT:
+         tObj = ctx->Texture.Unit[texUnit].Current2D;
+         break;
+      case TEXTURE_3D_BIT:
+         tObj = ctx->Texture.Unit[texUnit].Current3D;
+         break;
+      case TEXTURE_CUBE_BIT:
+         tObj = ctx->Texture.Unit[texUnit].CurrentCubeMap;
+         break;
+      case TEXTURE_RECT_BIT:
+         tObj = ctx->Texture.Unit[texUnit].CurrentRect;
+         break;
+      default:
+         _mesa_problem(ctx, "Bad texture in _swrast_validate_texture_sample");
+         return;
+      }
+      if (!tObj->Complete) {
+         _mesa_test_texobj_completeness(ctx,
+                                        (struct gl_texture_object *) tObj );
+      }
+   }
+
    swrast->TextureSample[texUnit] =
       _swrast_choose_texture_sample_func( ctx, tObj );
 
    swrast->TextureSample[texUnit]( ctx, texUnit, tObj, n, texcoords,
-                                  lambda, rgba );
+                                   lambda, rgba );
 
    /* GL_SGI_texture_color_table */
    if (ctx->Texture.Unit[texUnit].ColorTableEnabled) {
index 147b5248d4cbb0bf485884c14354219937475436..c55080c0aacd04302c08832989c0a792af8b9555 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_nvfragprog.c,v 1.6 2003/03/04 16:34:03 brianp Exp $ */
+/* $Id: s_nvfragprog.c,v 1.7 2003/03/14 15:41:00 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -33,7 +33,7 @@
 #include "macros.h"
 
 #include "s_nvfragprog.h"
-
+#include "s_texture.h"
 
 
 /**
  */
 static void
 fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLuint unit,
-             GLuint targetIndex, GLfloat color[4] )
+             GLuint targetBit, GLfloat color[4] )
 {
    const GLfloat *lambda = NULL;
    GLchan rgba[4];
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const struct gl_texture_object *texObj = NULL;
 
-   switch (targetIndex) {
-      case TEXTURE_1D_INDEX:
+   switch (targetBit) {
+      case TEXTURE_1D_BIT:
          texObj = ctx->Texture.Unit[unit].Current1D;
          break;
-      case TEXTURE_2D_INDEX:
+      case TEXTURE_2D_BIT:
          texObj = ctx->Texture.Unit[unit].Current2D;
          break;
-      case TEXTURE_3D_INDEX:
+      case TEXTURE_3D_BIT:
          texObj = ctx->Texture.Unit[unit].Current3D;
          break;
-      case TEXTURE_CUBE_INDEX:
+      case TEXTURE_CUBE_BIT:
          texObj = ctx->Texture.Unit[unit].CurrentCubeMap;
          break;
-      case TEXTURE_RECT_INDEX:
+      case TEXTURE_RECT_BIT:
          texObj = ctx->Texture.Unit[unit].CurrentRect;
          break;
       default:
@@ -69,8 +69,12 @@ fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLuint unit,
    }
 
    swrast->TextureSample[unit](ctx, unit, texObj, 1,
-                               (const GLfloat (*)[4]) &texcoord,
+                               (const GLfloat (*)[4]) texcoord,
                                lambda, &rgba);
+   color[0] = CHAN_TO_FLOAT(rgba[0]);
+   color[1] = CHAN_TO_FLOAT(rgba[1]);
+   color[2] = CHAN_TO_FLOAT(rgba[2]);
+   color[3] = CHAN_TO_FLOAT(rgba[3]);
 }
 
 
@@ -80,7 +84,7 @@ fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLuint unit,
 static void
 fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
                    const GLfloat dtdx[4], const GLfloat dtdy[4],
-                   GLuint unit, GLuint targetIndex, GLfloat color[4] )
+                   GLuint unit, GLuint targetBit, GLfloat color[4] )
 {
    /* XXX to do */
 
@@ -259,7 +263,9 @@ store_vector4( const struct fp_instruction *inst,
 
 
 /**
- * Execute the given vertex program
+ * Execute the given vertex program.
+ * NOTE: we do everything in single-precision floating point; we don't
+ * currently observe the single/half/fixed-precision qualifiers.
  * \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
  */
 static GLboolean
@@ -696,7 +702,7 @@ execute_program(GLcontext *ctx, const struct fragment_program *program)
                GLfloat texcoord[4], color[4];
                fetch_vector4( &inst->SrcReg[0], machine, texcoord );
                fetch_texel( ctx, texcoord, inst->TexSrcUnit,
-                            inst->TexSrcIndex, color );
+                            inst->TexSrcBit, color );
                store_vector4( inst, machine, color );
             }
             break;
@@ -708,7 +714,7 @@ execute_program(GLcontext *ctx, const struct fragment_program *program)
                fetch_vector4( &inst->SrcReg[1], machine, dtdx );
                fetch_vector4( &inst->SrcReg[2], machine, dtdy );
                fetch_texel_deriv( ctx, texcoord, dtdx, dtdy, inst->TexSrcUnit,
-                                  inst->TexSrcIndex, color );
+                                  inst->TexSrcBit, color );
                store_vector4( inst, machine, color );
             }
             break;
@@ -721,7 +727,7 @@ execute_program(GLcontext *ctx, const struct fragment_program *program)
                texcoord[1] /= texcoord[3];
                texcoord[2] /= texcoord[3];
                fetch_texel( ctx, texcoord, inst->TexSrcUnit,
-                            inst->TexSrcIndex, color );
+                            inst->TexSrcBit, color );
                store_vector4( inst, machine, color );
             }
             break;
index 76a45b96b5ea95cafd9502df8bdc41fdfb0244ac..538102f41ff572a8db59ea81a222963b197d589d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_triangle.c,v 1.67 2003/03/01 01:50:26 brianp Exp $ */
+/* $Id: s_triangle.c,v 1.68 2003/03/14 15:41:00 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -1066,6 +1066,7 @@ _swrast_choose_triangle( GLcontext *ctx )
 
          /* First see if we can use an optimized 2-D texture function */
          if (ctx->Texture._EnabledUnits == 1
+             && !ctx->FragmentProgram.Enabled
              && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
              && texObj2D->WrapS==GL_REPEAT
             && texObj2D->WrapT==GL_REPEAT