summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2003-07-21 04:22:40 +0000
committerBrian Paul <brian.paul@tungstengraphics.com>2003-07-21 04:22:40 +0000
commit08ff059f203f05a0cc417a46fe37f83929963db5 (patch)
treea60fb074a49d3430f3a62c0319db1a7e1ef50224
parent190c11e06d0f33c6815c19f36bb6f8f90d2ac2be (diff)
Initial implementation of GL_MESA_program_debug - a vertex/fragment program
debugging extension.
-rw-r--r--src/mesa/main/arbprogram.c216
-rw-r--r--src/mesa/main/arbprogram.h9
-rw-r--r--src/mesa/main/config.h1
-rw-r--r--src/mesa/main/context.c1
-rw-r--r--src/mesa/main/dlist.c1
-rw-r--r--src/mesa/main/enable.c18
-rw-r--r--src/mesa/main/extensions.c6
-rw-r--r--src/mesa/main/get.c108
-rw-r--r--src/mesa/main/mtypes.h15
-rw-r--r--src/mesa/main/nvfragparse.c37
-rw-r--r--src/mesa/main/nvfragparse.h8
-rw-r--r--src/mesa/main/nvfragprog.h9
-rw-r--r--src/mesa/main/nvvertparse.c19
-rw-r--r--src/mesa/main/nvvertparse.h5
-rw-r--r--src/mesa/main/nvvertprog.h2
-rw-r--r--src/mesa/swrast/s_nvfragprog.c26
16 files changed, 461 insertions, 20 deletions
diff --git a/src/mesa/main/arbprogram.c b/src/mesa/main/arbprogram.c
index 08d72fafc0..20118d45a1 100644
--- a/src/mesa/main/arbprogram.c
+++ b/src/mesa/main/arbprogram.c
@@ -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;
+ }
+
+}
diff --git a/src/mesa/main/arbprogram.h b/src/mesa/main/arbprogram.h
index 7f4dd87758..bc5a6626ed 100644
--- a/src/mesa/main/arbprogram.h
+++ b/src/mesa/main/arbprogram.h
@@ -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
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index cb94a29f27..bbffcd05be 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -256,6 +256,7 @@
#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
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index b4b9659d92..b44f74be4a 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -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 );
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index 928b74cb54..5588f442d3 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -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);
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index de08fa3513..3106a987f8 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -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;
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index efc92673ab..95c680c9ca 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -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;
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index a237775385..3cf8453c78 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -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;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index bac711de1c..cb408293d0 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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;
diff --git a/src/mesa/main/nvfragparse.c b/src/mesa/main/nvfragparse.c
index 38da433197..4f1df534b9 100644
--- a/src/mesa/main/nvfragparse.c
+++ b/src/mesa/main/nvfragparse.c
@@ -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];
+}
diff --git a/src/mesa/main/nvfragparse.h b/src/mesa/main/nvfragparse.h
index 16f96ceca2..849a7fbc7d 100644
--- a/src/mesa/main/nvfragparse.h
+++ b/src/mesa/main/nvfragparse.h
@@ -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
diff --git a/src/mesa/main/nvfragprog.h b/src/mesa/main/nvfragprog.h
index 491fcdda6c..2f2434b42e 100644
--- a/src/mesa/main/nvfragprog.h
+++ b/src/mesa/main/nvfragprog.h
@@ -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
diff --git a/src/mesa/main/nvvertparse.c b/src/mesa/main/nvvertparse.c
index 2e18c7abe4..9d0cd5f54d 100644
--- a/src/mesa/main/nvvertparse.c
+++ b/src/mesa/main/nvvertparse.c
@@ -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];
+}
diff --git a/src/mesa/main/nvvertparse.h b/src/mesa/main/nvvertparse.h
index 5949b9228b..205885f45c 100644
--- a/src/mesa/main/nvvertparse.h
+++ b/src/mesa/main/nvvertparse.h
@@ -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
diff --git a/src/mesa/main/nvvertprog.h b/src/mesa/main/nvvertprog.h
index 44207e2e4c..411426e963 100644
--- a/src/mesa/main/nvvertprog.h
+++ b/src/mesa/main/nvvertprog.h
@@ -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
diff --git a/src/mesa/swrast/s_nvfragprog.c b/src/mesa/swrast/s_nvfragprog.c
index c728aa3d00..1416e7981a 100644
--- a/src/mesa/swrast/s_nvfragprog.c
+++ b/src/mesa/swrast/s_nvfragprog.c
@@ -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);*/
}
}