Initial implementation of GL_MESA_program_debug - a vertex/fragment program
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 21 Jul 2003 04:22:40 +0000 (04:22 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 21 Jul 2003 04:22:40 +0000 (04:22 +0000)
debugging extension.

16 files changed:
src/mesa/main/arbprogram.c
src/mesa/main/arbprogram.h
src/mesa/main/config.h
src/mesa/main/context.c
src/mesa/main/dlist.c
src/mesa/main/enable.c
src/mesa/main/extensions.c
src/mesa/main/get.c
src/mesa/main/mtypes.h
src/mesa/main/nvfragparse.c
src/mesa/main/nvfragparse.h
src/mesa/main/nvfragprog.h
src/mesa/main/nvvertparse.c
src/mesa/main/nvvertparse.h
src/mesa/main/nvvertprog.h
src/mesa/swrast/s_nvfragprog.c

index 08d72fafc07b8c86b1c43cbcbb0db6231b681e9c..20118d45a1fb4a6039792c0ebaec5cfa1a484b30 100644 (file)
@@ -37,7 +37,9 @@
 #include "macros.h"
 #include "mtypes.h"
 #include "nvprogram.h"
+#include "nvfragparse.h"
 #include "nvfragprog.h"
+#include "nvvertparse.h"
 #include "nvvertprog.h"
 
 
@@ -482,7 +484,7 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
       prog = &(ctx->VertexProgram.Current->Base);
    }
    else if (target == GL_FRAGMENT_PROGRAM_ARB
-            && ctx->Extensions.ARB_vertex_program) {
+            && ctx->Extensions.ARB_fragment_program) {
       prog = &(ctx->FragmentProgram.Current->Base);
    }
    else {
@@ -702,3 +704,215 @@ _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
 
    MEMCPY(string, prog->String, _mesa_strlen((char *) prog->String));
 }
+
+
+
+/* XXX temporary */
+void
+glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
+                      GLvoid *data)
+{
+   _mesa_ProgramCallbackMESA(target, callback, data);
+}
+
+
+void
+_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
+                          GLvoid *data)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   switch (target) {
+      case GL_FRAGMENT_PROGRAM_ARB:
+         if (!ctx->Extensions.ARB_fragment_program) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
+            return;
+         }
+         ctx->FragmentProgram.Callback = callback;
+         ctx->FragmentProgram.CallbackData = data;
+         break;
+      case GL_FRAGMENT_PROGRAM_NV:
+         if (!ctx->Extensions.NV_fragment_program) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
+            return;
+         }
+         ctx->FragmentProgram.Callback = callback;
+         ctx->FragmentProgram.CallbackData = data;
+         break;
+      case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
+         if (!ctx->Extensions.ARB_vertex_program &&
+             !ctx->Extensions.ARB_vertex_program) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
+            return;
+         }
+         ctx->VertexProgram.Callback = callback;
+         ctx->VertexProgram.CallbackData = data;
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
+         return;
+   }
+}
+
+
+/* XXX temporary */
+void
+glGetProgramRegisterfvMESA(GLenum target,
+                           GLsizei len, const GLubyte *registerName,
+                           GLfloat *v)
+{
+   _mesa_GetProgramRegisterfvMESA(target, len, registerName, v);
+}
+
+
+void
+_mesa_GetProgramRegisterfvMESA(GLenum target,
+                               GLsizei len, const GLubyte *registerName,
+                               GLfloat *v)
+{
+   char reg[1000];
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* We _should_ be inside glBegin/glEnd */
+#if 0
+   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA");
+      return;
+   }
+#endif
+
+   /* make null-terminated copy of registerName */
+   _mesa_memcpy(reg, registerName, len);
+   reg[len] = 0;
+
+   switch (target) {
+      case GL_VERTEX_PROGRAM_NV:
+         if (!ctx->Extensions.ARB_vertex_program &&
+             !ctx->Extensions.NV_vertex_program) {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetProgramRegisterfvMESA(target)");
+            return;
+         }
+         if (!ctx->VertexProgram.Enabled) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glGetProgramRegisterfvMESA");
+            return;
+         }
+         /* GL_NV_vertex_program */
+         if (reg[0] == 'R') {
+            /* Temp register */
+            GLint i = _mesa_atoi(reg + 1);
+            if (i >= ctx->Const.MaxVertexProgramTemps) {
+               _mesa_error(ctx, GL_INVALID_VALUE,
+                           "glGetProgramRegisterfvMESA(registerName)");
+               return;
+            }
+            COPY_4V(v, ctx->VertexProgram.Machine.Registers
+                    [VP_TEMP_REG_START + i]);
+         }
+         else if (reg[0] == 'v' && reg[1] == '[') {
+            /* Vertex Input attribute */
+            GLint i;
+            for (i = 0; i < ctx->Const.MaxVertexProgramAttribs; i++) {
+               const char *name = _mesa_nv_vertex_input_register_name(i);
+               if (_mesa_strncmp(reg + 2, name, 4) == 0) {
+                  COPY_4V(v, ctx->VertexProgram.Machine.Registers
+                          [VP_INPUT_REG_START + i]);
+                  return;
+               }
+            }
+            _mesa_error(ctx, GL_INVALID_VALUE,
+                        "glGetProgramRegisterfvMESA(registerName)");
+            return;
+         }
+         else if (reg[0] == 'o' && reg[1] == '[') {
+            /* Vertex output attribute */
+         }
+         /* GL_ARB_vertex_program */
+         else if (_mesa_strncmp(reg, "vertex.", 7) == 0) {
+
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_VALUE,
+                        "glGetProgramRegisterfvMESA(registerName)");
+            return;
+         }
+         break;
+      case GL_FRAGMENT_PROGRAM_ARB:
+         if (!ctx->Extensions.ARB_fragment_program) {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetProgramRegisterfvMESA(target)");
+            return;
+         }
+         if (!ctx->FragmentProgram.Enabled) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glGetProgramRegisterfvMESA");
+            return;
+         }
+         /* XXX to do */
+         break;
+      case GL_FRAGMENT_PROGRAM_NV:
+         if (!ctx->Extensions.NV_fragment_program) {
+            _mesa_error(ctx, GL_INVALID_ENUM,
+                        "glGetProgramRegisterfvMESA(target)");
+            return;
+         }
+         if (!ctx->FragmentProgram.Enabled) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glGetProgramRegisterfvMESA");
+            return;
+         }
+         if (reg[0] == 'R') {
+            /* Temp register */
+            GLint i = _mesa_atoi(reg + 1);
+            if (i >= ctx->Const.MaxFragmentProgramTemps) {
+               _mesa_error(ctx, GL_INVALID_VALUE,
+                           "glGetProgramRegisterfvMESA(registerName)");
+               return;
+            }
+            COPY_4V(v,
+               ctx->FragmentProgram.Machine.Registers[FP_TEMP_REG_START + i]);
+         }
+         else if (reg[0] == 'f' && reg[1] == '[') {
+            /* Fragment input attribute */
+            GLint i;
+            for (i = 0; i < ctx->Const.MaxFragmentProgramAttribs; i++) {
+               const char *name = _mesa_nv_fragment_input_register_name(i);
+               if (_mesa_strncmp(reg + 2, name, 4) == 0) {
+                  COPY_4V(v, ctx->FragmentProgram.Machine.Registers
+                          [FP_INPUT_REG_START + i]);
+                  return;
+               }
+            }
+            _mesa_error(ctx, GL_INVALID_VALUE,
+                        "glGetProgramRegisterfvMESA(registerName)");
+            return;
+         }
+         else if (_mesa_strcmp(reg, "o[COLR]") == 0) {
+            /* Fragment output color */
+            COPY_4V(v, ctx->FragmentProgram.Machine.Registers
+                    [FP_OUTPUT_REG_START + FRAG_OUTPUT_COLR]);
+         }
+         else if (_mesa_strcmp(reg, "o[COLH]") == 0) {
+            /* Fragment output color */
+            COPY_4V(v, ctx->FragmentProgram.Machine.Registers
+                    [FP_OUTPUT_REG_START + FRAG_OUTPUT_COLH]);
+         }
+         else if (_mesa_strcmp(reg, "o[DEPR]") == 0) {
+            /* Fragment output depth */
+            COPY_4V(v, ctx->FragmentProgram.Machine.Registers
+                    [FP_OUTPUT_REG_START + FRAG_OUTPUT_DEPR]);
+         }
+         else {
+            _mesa_error(ctx, GL_INVALID_VALUE,
+                        "glGetProgramRegisterfvMESA(registerName)");
+            return;
+         }
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM,
+                     "glGetProgramRegisterfvMESA(target)");
+         return;
+   }
+
+}
index 7f4dd877580b4cb6fe41b889e880d71345007923..bc5a6626ed585c2c88c163fe3c622b0d317be637 100644 (file)
@@ -125,5 +125,12 @@ extern void
 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string);
 
 
-#endif
+extern void
+_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
+                          GLvoid *data);
 
+extern void
+_mesa_GetProgramRegisterfvMESA(GLenum target, GLsizei len,
+                               const GLubyte *registerName, GLfloat *v);
+
+#endif
index cb94a29f279b6ee070e1d58e4ec38bac4e8017d1..bbffcd05be3e0af8888fd9f4d585312ace85b7ee 100644 (file)
 #define FEATURE_ARB_vertex_program 1
 #define FEATURE_ARB_fragment_program 1
 #define FEATURE_ARB_occlusion_query 1
+#define FEATURE_MESA_program_debug 1
 #define FEATURE_NV_fence 1
 #define FEATURE_userclip 1
 #define FEATURE_texgen 1
index b4b9659d924227cf4a455e46a1cb7a3cd98e56e1..b44f74be4a10a294c59796a6afd04ae1937b88e4 100644 (file)
@@ -1105,6 +1105,7 @@ init_attrib_groups( GLcontext *ctx )
    _mesa_init_pixel( ctx );
    _mesa_init_point( ctx );
    _mesa_init_polygon( ctx );
+   /* XXX _mesa_init_program( ctx ); */
    _mesa_init_rastpos( ctx );
    _mesa_init_stencil( ctx );
    _mesa_init_transform( ctx );
index 928b74cb5408aa2314ad1c408131efe01b6b0926..5588f442d38e9edd9d8d18dc26ff28fe8b46b3f8 100644 (file)
@@ -5355,6 +5355,7 @@ _mesa_CallList( GLuint list )
    /* VERY IMPORTANT:  Save the CompileFlag status, turn it off, */
    /* execute the display list, and restore the CompileFlag. */
 
+   printf("%s %d\n", __FUNCTION__, list);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glCallList %d\n", list); 
index de08fa351355defe6ea7f23d8fb7c0dd4f3729ef..3106a987f8a603c372796299166baa07befa4411 100644 (file)
@@ -971,6 +971,16 @@ void _mesa_set_enable( GLcontext *ctx, GLenum cap, GLboolean state )
          ctx->Depth.BoundsTest = state;
          break;
 
+      /* GL_MESA_program_debug */
+      case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION(MESA_program_debug, cap);
+         ctx->FragmentProgram.CallbackEnabled = state;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION(MESA_program_debug, cap);
+         ctx->VertexProgram.CallbackEnabled = state;
+         break;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "%s(0x%x)", state ? "glEnable" : "glDisable", cap);
@@ -1401,6 +1411,14 @@ _mesa_IsEnabled( GLenum cap )
          CHECK_EXTENSION(EXT_depth_bounds_test);
          return ctx->Depth.BoundsTest;
 
+      /* GL_MESA_program_debug */
+      case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION(MESA_program_debug);
+         return ctx->FragmentProgram.CallbackEnabled;
+      case GL_VERTEX_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION(MESA_program_debug);
+         return ctx->VertexProgram.CallbackEnabled;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
         return GL_FALSE;
index efc92673ab6873fbf867906bccb792a771a28735..95c680c9cad10703a8b454c7b78805609ec0e68b 100644 (file)
@@ -115,6 +115,7 @@ static const struct {
    { OFF, "GL_INGR_blend_func_separate",       F(EXT_blend_func_separate) },
    { OFF, "GL_MESA_pack_invert",               F(MESA_pack_invert) },
    { OFF, "GL_MESA_packed_depth_stencil",      F(MESA_packed_depth_stencil) },
+   { OFF, "GL_MESA_program_debug",             F(MESA_program_debug) },
    { OFF, "GL_MESA_resize_buffers",            F(MESA_resize_buffers) },
    { OFF, "GL_MESA_ycbcr_texture",             F(MESA_ycbcr_texture) },
    { ON,  "GL_MESA_window_pos",                F(ARB_window_pos) },
@@ -151,7 +152,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
 {
    ctx->Extensions.ARB_depth_texture = GL_TRUE;
 #if FEATURE_ARB_fragment_program
-   /*ctx->Extensions.ARB_fragment_program = GL_TRUE;*/
+   ctx->Extensions.ARB_fragment_program = GL_TRUE;
 #endif
    ctx->Extensions.ARB_imaging = GL_TRUE;
    ctx->Extensions.ARB_multitexture = GL_TRUE;
@@ -193,6 +194,9 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
    ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
    ctx->Extensions.HP_occlusion_test = GL_TRUE;
    ctx->Extensions.MESA_pack_invert = GL_TRUE;
+#if FEATURE_MESA_program_debug
+   ctx->Extensions.MESA_program_debug = GL_TRUE;
+#endif
    ctx->Extensions.MESA_resize_buffers = GL_TRUE;
    ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
    ctx->Extensions.NV_blend_square = GL_TRUE;
index a23777538588eca24f2c051cd285dd97107de210..3cf8453c78232fa6b997d2524490fa7eb1e92117 100644 (file)
@@ -1630,6 +1630,25 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
          params[1] = FLOAT_TO_BOOL(ctx->Depth.BoundsMax);
          break;
 
+#if FEATURE_MESA_program_debug
+      case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_B(MESA_program_debug, pname);
+         *params = ctx->FragmentProgram.CallbackEnabled;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_B(MESA_program_debug, pname);
+         *params = ctx->VertexProgram.CallbackEnabled;
+         break;
+      case GL_FRAGMENT_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_B(MESA_program_debug, pname);
+         *params = INT_TO_BOOL(ctx->FragmentProgram.CurrentPosition);
+         break;
+      case GL_VERTEX_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_B(MESA_program_debug, pname);
+         *params = INT_TO_BOOL(ctx->VertexProgram.CurrentPosition);
+         break;
+#endif
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname);
    }
@@ -3148,6 +3167,25 @@ _mesa_GetDoublev( GLenum pname, GLdouble *params )
          params[1] = ctx->Depth.BoundsMax;
          break;
 
+#if FEATURE_MESA_program_debug
+      case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_D(MESA_program_debug, pname);
+         *params = (GLdouble) ctx->FragmentProgram.CallbackEnabled;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_D(MESA_program_debug, pname);
+         *params = (GLdouble) ctx->VertexProgram.CallbackEnabled;
+         break;
+      case GL_FRAGMENT_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_D(MESA_program_debug, pname);
+         *params = (GLdouble) ctx->FragmentProgram.CurrentPosition;
+         break;
+      case GL_VERTEX_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_D(MESA_program_debug, pname);
+         *params = (GLdouble) ctx->VertexProgram.CurrentPosition;
+         break;
+#endif
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetDoublev(pname=0x%x)", pname);
    }
@@ -4642,6 +4680,25 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
          params[1] = ctx->Depth.BoundsMax;
          break;
 
+#if FEATURE_MESA_program_debug
+      case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_F(MESA_program_debug, pname);
+         *params = (GLfloat) ctx->FragmentProgram.CallbackEnabled;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_F(MESA_program_debug, pname);
+         *params = (GLfloat) ctx->VertexProgram.CallbackEnabled;
+         break;
+      case GL_FRAGMENT_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_F(MESA_program_debug, pname);
+         *params = (GLfloat) ctx->FragmentProgram.CurrentPosition;
+         break;
+      case GL_VERTEX_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_F(MESA_program_debug, pname);
+         *params = (GLfloat) ctx->VertexProgram.CurrentPosition;
+         break;
+#endif
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(0x%x)", pname);
    }
@@ -4672,6 +4729,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
    if (!params)
       return;
 
+#if 0
    /* We need this in order to get correct results for
     * GL_OCCLUSION_TEST_RESULT_HP.  There might be other important cases.
     */
@@ -4683,6 +4741,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
    if (ctx->Driver.GetIntegerv
        && (*ctx->Driver.GetIntegerv)(ctx, pname, params))
       return;
+#endif
 
    switch (pname) {
       case GL_ACCUM_RED_BITS:
@@ -6174,6 +6233,25 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
          params[1] = (GLint) ctx->Depth.BoundsMax;
          break;
 
+#if FEATURE_MESA_program_debug
+      case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_I(MESA_program_debug, pname);
+         *params = (GLint) ctx->FragmentProgram.CallbackEnabled;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_MESA:
+         CHECK_EXTENSION_I(MESA_program_debug, pname);
+         *params = (GLint) ctx->VertexProgram.CallbackEnabled;
+         break;
+      case GL_FRAGMENT_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_I(MESA_program_debug, pname);
+         *params = (GLint) ctx->FragmentProgram.CurrentPosition;
+         break;
+      case GL_VERTEX_PROGRAM_POSITION_MESA:
+         CHECK_EXTENSION_I(MESA_program_debug, pname);
+         *params = (GLint) ctx->VertexProgram.CurrentPosition;
+         break;
+#endif
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname);
    }
@@ -6239,6 +6317,36 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
       case GL_SELECTION_BUFFER_POINTER:
          *params = ctx->Select.Buffer;
          break;
+#if FEATURE_MESA_program_debug
+      case GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA:
+         if (!ctx->Extensions.MESA_program_debug) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
+            return;
+         }
+         *params = (GLvoid *) ctx->FragmentProgram.Callback;
+         break;
+      case GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA:
+         if (!ctx->Extensions.MESA_program_debug) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
+            return;
+         }
+         *params = ctx->FragmentProgram.CallbackData;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA:
+         if (!ctx->Extensions.MESA_program_debug) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
+            return;
+         }
+         *params = (GLvoid *) ctx->VertexProgram.Callback;
+         break;
+      case GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA:
+         if (!ctx->Extensions.MESA_program_debug) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
+            return;
+         }
+         *params = ctx->VertexProgram.CallbackData;
+         break;
+#endif
       default:
          _mesa_error( ctx, GL_INVALID_ENUM, "glGetPointerv" );
          return;
index bac711de1ce34f17c5f96abe1a6e1ae08132e5a2..cb408293d098583e23f28c95889da8a1aa8f65eb 100644 (file)
@@ -1501,6 +1501,13 @@ struct vertex_program_state
 
    GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
    GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
+
+#if FEATURE_MESA_program_debug
+   GLprogramcallbackMESA Callback;
+   GLvoid *CallbackData;
+   GLboolean CallbackEnabled;
+   GLuint CurrentPosition;
+#endif
 };
 
 
@@ -1512,6 +1519,13 @@ struct fragment_program_state
    GLboolean Enabled;                    /* GL_VERTEX_PROGRAM_NV */
    struct fragment_program *Current;     /* ptr to currently bound program */
    struct fp_machine Machine;            /* machine state */
+
+#if FEATURE_MESA_program_debug
+   GLprogramcallbackMESA Callback;
+   GLvoid *CallbackData;
+   GLboolean CallbackEnabled;
+   GLuint CurrentPosition;
+#endif
 };
 
 /*@}*/
@@ -1735,6 +1749,7 @@ struct gl_extensions {
    GLboolean IBM_rasterpos_clip;
    GLboolean MESA_pack_invert;
    GLboolean MESA_packed_depth_stencil;
+   GLboolean MESA_program_debug;
    GLboolean MESA_resize_buffers;
    GLboolean MESA_ycbcr_texture;
    GLboolean NV_blend_square;
index 38da43319717e5cde711b0eb4c8a800ee36c9db2..4f1df534b98120aaf1cfaad769ce2c0f4ae042ac 100644 (file)
@@ -126,6 +126,7 @@ struct parse_state {
    GLcontext *ctx;
    const GLubyte *start;              /* start of program string */
    const GLubyte *pos;                /* current position */
+   const GLubyte *curLine;
    struct fragment_program *program;  /* current program */
 
    GLuint numParameters;
@@ -332,8 +333,9 @@ static GLboolean IsWhitespace(GLubyte b)
  * \return <= 0 we found an error, else, return number of characters parsed.
  */
 static GLint
-GetToken(const GLubyte *str, GLubyte *token)
+GetToken(struct parse_state *parseState, GLubyte *token)
 {
+   const GLubyte *str = parseState->pos;
    GLint i = 0, j = 0;
 
    token[0] = 0;
@@ -345,9 +347,13 @@ GetToken(const GLubyte *str, GLubyte *token)
          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
             i++;
          }
+         if (str[i] == '\n' || str[i] == '\r')
+            parseState->curLine = str + i + 1;
       }
       else {
          /* skip whitespace */
+         if (str[i] == '\n' || str[i] == '\r')
+            parseState->curLine = str + i + 1;
          i++;
       }
    }
@@ -393,7 +399,7 @@ static GLboolean
 Parse_Token(struct parse_state *parseState, GLubyte *token)
 {
    GLint i;
-   i = GetToken(parseState->pos, token);
+   i = GetToken(parseState, token);
    if (i <= 0) {
       parseState->pos += (-i);
       return GL_FALSE;
@@ -410,7 +416,7 @@ static GLboolean
 Peek_Token(struct parse_state *parseState, GLubyte *token)
 {
    GLint i, len;
-   i = GetToken(parseState->pos, token);
+   i = GetToken(parseState, token);
    if (i <= 0) {
       parseState->pos += (-i);
       return GL_FALSE;
@@ -510,9 +516,13 @@ Parse_String(struct parse_state *parseState, const char *pattern)
          while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
             parseState->pos += 1;
          }
+         if (*parseState->pos == '\n' || *parseState->pos == '\r')
+            parseState->curLine = parseState->pos + 1;
       }
       else {
          /* skip whitespace */
+         if (*parseState->pos == '\n' || *parseState->pos == '\r')
+            parseState->curLine = parseState->pos + 1;
          parseState->pos += 1;
       }
    }
@@ -1337,6 +1347,8 @@ Parse_InstructionSequence(struct parse_state *parseState,
       }
       else if (Parse_String(parseState, "END")) {
          inst->Opcode = FP_OPCODE_END;
+         inst->StringPos = parseState->curLine - parseState->start;
+         assert(inst->StringPos >= 0);
          parseState->numInst++;
          if (Parse_Token(parseState, token)) {
             RETURN_ERROR1("Code after END opcode.");
@@ -1362,6 +1374,8 @@ Parse_InstructionSequence(struct parse_state *parseState,
          inst->Precision = instMatch.suffixes & (_R | _H | _X);
          inst->Saturate = (instMatch.suffixes & (_S)) ? GL_TRUE : GL_FALSE;
          inst->UpdateCondRegister = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
+         inst->StringPos = parseState->curLine - parseState->start;
+         assert(inst->StringPos >= 0);
 
          /*
           * parse the input and output operands
@@ -1491,6 +1505,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
    parseState.start = programString;
    parseState.program = program;
    parseState.numInst = 0;
+   parseState.curLine = programString;
 
    /* Reset error state */
    _mesa_set_program_error(ctx, -1, NULL);
@@ -1845,3 +1860,19 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
    }
    _mesa_printf("END\n");
 }
+
+
+const char *
+_mesa_nv_fragment_input_register_name(GLuint i)
+{
+   ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
+   return InputRegisters[i];
+}
+
+
+const char *
+_mesa_nv_fragment_output_register_name(GLuint i)
+{
+   ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
+   return OutputRegisters[i];
+}
index 16f96ceca2fe57e354d60dff5e356ff7fdf3c844..849a7fbc7d6752b1362983d7ccd5eb33fe4b91cf 100644 (file)
@@ -41,4 +41,12 @@ extern void
 _mesa_print_nv_fragment_program(const struct fragment_program *program);
 
 
+extern const char *
+_mesa_nv_fragment_input_register_name(GLuint i);
+
+
+extern const char *
+_mesa_nv_fragment_output_register_name(GLuint i);
+
+
 #endif
index 491fcdda6c6f29b20f9bc762b071ac826185a9d7..2f2434b42ef7cd36c762f46f8889dffc95d4bba5 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
@@ -24,8 +23,8 @@
  */
 
 
-/* Private vertex program types and constants only used by files
- * related to vertex programs.
+/* Private fragment program types and constants only used by files
+ * related to fragment programs.
  */
 
 
@@ -166,8 +165,10 @@ struct fp_instruction
    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 */
+#if FEATURE_MESA_program_debug
+   GLint StringPos;
+#endif
 };
 
 
-
 #endif
index 2e18c7abe430917023b14f5521c934beacd01ae2..9d0cd5f54d4d8db0e8820f97f830693a91da0112 100644 (file)
@@ -262,12 +262,12 @@ Parse_String(struct parse_state *parseState, const char *pattern)
 
 /**********************************************************************/
 
-static const char *InputRegisters[] = {
+static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
    "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
 };
 
-static const char *OutputRegisters[] = {
+static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
    "HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ",
    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
 };
@@ -1472,3 +1472,18 @@ _mesa_print_nv_vertex_program(const struct vertex_program *program)
    }
 }
 
+
+const char *
+_mesa_nv_vertex_input_register_name(GLuint i)
+{
+   ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS);
+   return InputRegisters[i];
+}
+
+
+const char *
+_mesa_nv_vertex_output_register_name(GLuint i)
+{
+   ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
+   return OutputRegisters[i];
+}
index 5949b9228b60bbfcd8bcca8bf37d2d1375e3f885..205885f45c38e1412d0f1a529ec33a1072625221 100644 (file)
@@ -41,5 +41,10 @@ _mesa_print_nv_vertex_instruction(const struct vp_instruction *inst);
 extern void
 _mesa_print_nv_vertex_program(const struct vertex_program *program);
 
+extern const char *
+_mesa_nv_vertex_input_register_name(GLuint i);
+
+extern const char *
+_mesa_nv_vertex_output_register_name(GLuint i);
 
 #endif
index 44207e2e4c883d8af1573205b17148aa1e772f06..411426e963be4536acbb5c5a678d01923dfb1606 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
@@ -28,6 +27,7 @@
  * related to vertex programs.
  */
 
+
 #ifndef NVVERTPROG_H
 #define NVVERTPROG_H
 
index c728aa3d00611951e387cc2ed9f9adaa2bafa5e0..1416e7981a193f68fe74e455ae99091985c657e3 100644 (file)
@@ -527,6 +527,14 @@ execute_program( GLcontext *ctx,
 
    for (pc = 0; pc < maxInst; pc++) {
       const struct fp_instruction *inst = program->Instructions + pc;
+
+      if (ctx->FragmentProgram.CallbackEnabled &&
+          ctx->FragmentProgram.Callback) {
+         ctx->FragmentProgram.CurrentPosition = inst->StringPos;
+         ctx->FragmentProgram.Callback(program->Base.Target,
+                                       ctx->FragmentProgram.CallbackData);
+      }
+
       switch (inst->Opcode) {
          case FP_OPCODE_ADD:
             {
@@ -1105,8 +1113,12 @@ init_machine( GLcontext *ctx, struct fp_machine *machine,
               const struct fragment_program *program,
               const struct sw_span *span, GLuint col )
 {
+   GLuint inputsRead = program->InputsRead;
    GLuint j, u;
 
+   if (ctx->FragmentProgram.CallbackEnabled)
+      inputsRead = ~0;
+
    /* Clear temporary registers */
    _mesa_bzero(machine->Registers + FP_TEMP_REG_START,
                MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
@@ -1118,28 +1130,28 @@ init_machine( GLcontext *ctx, struct fp_machine *machine,
    }
 
    /* Load input registers */
-   if (program->InputsRead & (1 << FRAG_ATTRIB_WPOS)) {
+   if (inputsRead & (1 << FRAG_ATTRIB_WPOS)) {
       GLfloat *wpos = machine->Registers[FP_INPUT_REG_START+FRAG_ATTRIB_WPOS];
       wpos[0] = span->x + col;
       wpos[1] = span->y;
       wpos[2] = (GLfloat) span->array->z[col] / ctx->DepthMaxF;
       wpos[3] = span->w + col * span->dwdx;
    }
-   if (program->InputsRead & (1 << FRAG_ATTRIB_COL0)) {
+   if (inputsRead & (1 << FRAG_ATTRIB_COL0)) {
       GLfloat *col0 = machine->Registers[FP_INPUT_REG_START+FRAG_ATTRIB_COL0];
       col0[0] = CHAN_TO_FLOAT(span->array->rgba[col][RCOMP]);
       col0[1] = CHAN_TO_FLOAT(span->array->rgba[col][GCOMP]);
       col0[2] = CHAN_TO_FLOAT(span->array->rgba[col][BCOMP]);
       col0[3] = CHAN_TO_FLOAT(span->array->rgba[col][ACOMP]);
    }
-   if (program->InputsRead & (1 << FRAG_ATTRIB_COL1)) {
+   if (inputsRead & (1 << FRAG_ATTRIB_COL1)) {
       GLfloat *col1 = machine->Registers[FP_INPUT_REG_START+FRAG_ATTRIB_COL1];
       col1[0] = CHAN_TO_FLOAT(span->array->spec[col][RCOMP]);
       col1[1] = CHAN_TO_FLOAT(span->array->spec[col][GCOMP]);
       col1[2] = CHAN_TO_FLOAT(span->array->spec[col][BCOMP]);
       col1[3] = CHAN_TO_FLOAT(span->array->spec[col][ACOMP]);
    }
-   if (program->InputsRead & (1 << FRAG_ATTRIB_FOGC)) {
+   if (inputsRead & (1 << FRAG_ATTRIB_FOGC)) {
       GLfloat *fogc = machine->Registers[FP_INPUT_REG_START+FRAG_ATTRIB_FOGC];
       fogc[0] = span->array->fog[col];
       fogc[1] = 0.0F;
@@ -1147,11 +1159,11 @@ init_machine( GLcontext *ctx, struct fp_machine *machine,
       fogc[3] = 0.0F;
    }
    for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
-      if (program->InputsRead & (1 << (FRAG_ATTRIB_TEX0 + u))) {
+      if (inputsRead & (1 << (FRAG_ATTRIB_TEX0 + u))) {
          GLfloat *tex = machine->Registers[FP_INPUT_REG_START+FRAG_ATTRIB_TEX0+u];
-         ASSERT(ctx->Texture._EnabledCoordUnits & (1 << u));
+         /*ASSERT(ctx->Texture._EnabledCoordUnits & (1 << u));*/
          COPY_4V(tex, span->array->texcoords[u][col]);
-         ASSERT(tex[0] != 0 || tex[1] != 0 || tex[2] != 0);
+         /*ASSERT(tex[0] != 0 || tex[1] != 0 || tex[2] != 0);*/
       }
    }