Added PRINT instruction for GL_NV_fragment_program.
authorBrian Paul <brian.paul@tungstengraphics.com>
Sat, 18 Dec 2004 16:18:00 +0000 (16:18 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sat, 18 Dec 2004 16:18:00 +0000 (16:18 +0000)
src/mesa/shader/nvfragparse.c
src/mesa/shader/nvfragprog.h
src/mesa/shader/nvvertparse.c
src/mesa/shader/program.c
src/mesa/swrast/s_nvfragprog.c

index 5c71b4b4dfe6c4942cdf60525ecdf32dc6bc7f5a..bf1196cbf7ff8d3cb82cb333fa8003fae7ac46c7 100644 (file)
@@ -58,6 +58,7 @@
 #define INPUT_1V_T   7  /* one source vector, plus textureId */
 #define INPUT_3V_T   8  /* one source vector, plus textureId */
 #define INPUT_NONE   9
+#define INPUT_1V_S  10  /* a string and a vector register */
 #define OUTPUT_V    20
 #define OUTPUT_S    21
 #define OUTPUT_NONE 22
@@ -95,7 +96,7 @@ static const struct instruction_pattern Instructions[] = {
    { "EX2", FP_OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
    { "FLR", FP_OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
    { "FRC", FP_OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
-   { "KIL", FP_OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0                   },
+   { "KIL", FP_OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0                },
    { "LG2", FP_OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
    { "LIT", FP_OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
    { "LRP", FP_OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
@@ -124,12 +125,13 @@ static const struct instruction_pattern Instructions[] = {
    { "SUB", FP_OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
    { "TEX", FP_OPCODE_TEX, INPUT_1V_T, OUTPUT_V,              _C | _S },
    { "TXD", FP_OPCODE_TXD, INPUT_3V_T, OUTPUT_V,              _C | _S },
-   { "TXP", FP_OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V,              _C | _S },
+   { "TXP", FP_OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V,           _C | _S },
    { "UP2H",  FP_OPCODE_UP2H,  INPUT_1S, OUTPUT_V,            _C | _S },
    { "UP2US", FP_OPCODE_UP2US, INPUT_1S, OUTPUT_V,            _C | _S },
    { "UP4B",  FP_OPCODE_UP4B,  INPUT_1S, OUTPUT_V,            _C | _S },
    { "UP4UB", FP_OPCODE_UP4UB, INPUT_1S, OUTPUT_V,            _C | _S },
    { "X2D", FP_OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H |      _C | _S },
+   { "PRINT", FP_OPCODE_PRINT, INPUT_1V_S, OUTPUT_NONE, 0               },
    { NULL, (enum fp_opcode) -1, 0, 0, 0 }
 };
 
@@ -1190,6 +1192,60 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
 }
 
 
+static GLboolean
+Parse_PrintInstruction(struct parse_state *parseState,
+                       struct fp_instruction *inst)
+{
+   const GLubyte *str;
+   GLubyte *msg;
+   GLuint len;
+
+   /* The first argument is a literal string 'just like this' */
+   if (!Parse_String(parseState, "'"))
+      RETURN_ERROR1("Expected '");
+
+   str = parseState->pos;
+   for (len = 0; str[len] != '\''; len++) /* find closing quote */
+      ;
+   parseState->pos += len + 1;
+   msg = _mesa_malloc(len + 1);
+
+   _mesa_memcpy(msg, str, len);
+   msg[len] = 0;
+   inst->Data = msg;
+
+   if (Parse_String(parseState, ",")) {
+      /* got an optional register to print */
+      GLubyte token[100];
+      GetToken(parseState, token);
+      if (token[0] == 'o') {
+         /* dst reg */
+         if (!Parse_OutputReg(parseState, &inst->SrcReg[0].Index))
+            RETURN_ERROR;
+         inst->SrcReg[0].File = PROGRAM_OUTPUT;
+      }
+      else {
+         /* src reg */
+         if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+            RETURN_ERROR;
+      }
+   }
+   else {
+      /* File = 0 indicates no register to print */
+      inst->SrcReg[0].File = -1;
+   }
+
+   inst->SrcReg[0].Swizzle[0] = 0;
+   inst->SrcReg[0].Swizzle[1] = 1;
+   inst->SrcReg[0].Swizzle[2] = 2;
+   inst->SrcReg[0].Swizzle[3] = 3;
+   inst->SrcReg[0].NegateBase = GL_FALSE;
+   inst->SrcReg[0].Abs = GL_FALSE;
+   inst->SrcReg[0].NegateAbs = GL_FALSE;
+
+   return GL_TRUE;
+}
+
 
 static GLboolean
 Parse_InstructionSequence(struct parse_state *parseState,
@@ -1209,6 +1265,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
       inst->DstReg.CondSwizzle[1] = 1;
       inst->DstReg.CondSwizzle[2] = 2;
       inst->DstReg.CondSwizzle[3] = 3;
+      inst->Data = NULL;
 
       /* special instructions */
       if (Parse_String(parseState, "DEFINE")) {
@@ -1291,10 +1348,16 @@ Parse_InstructionSequence(struct parse_state *parseState,
                RETURN_ERROR1("Expected ,");
          }
          else if (instMatch.outputs == OUTPUT_NONE) {
-            ASSERT(instMatch.opcode == FP_OPCODE_KIL_NV);
-            /* This is a little weird, the cond code info is in the dest register */
-            if (!Parse_CondCodeMask(parseState, &inst->DstReg))
-               RETURN_ERROR;
+            if (instMatch.opcode == FP_OPCODE_KIL_NV) {
+               /* This is a little weird, the cond code info is in
+                * the dest register.
+                */
+               if (!Parse_CondCodeMask(parseState, &inst->DstReg))
+                  RETURN_ERROR;
+            }
+            else {
+               ASSERT(instMatch.opcode == FP_OPCODE_PRINT);
+            }
          }
 
          if (instMatch.inputs == INPUT_1V) {
@@ -1362,6 +1425,10 @@ Parse_InstructionSequence(struct parse_state *parseState,
                                       &inst->TexSrcBit))
                RETURN_ERROR;
          }
+         else if (instMatch.inputs == INPUT_1V_S) {
+            if (!Parse_PrintInstruction(parseState, inst))
+               RETURN_ERROR;
+         }
 
          /* end of statement semicolon */
          if (!Parse_String(parseState, ";"))
index 8f02f228770ee9bc577fb44ff24613d566da7b13..ddfc4993ed56c2e58c913bd66f32dda7526348bb 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.3
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -117,6 +117,7 @@ enum fp_opcode {
    FP_OPCODE_UP4UB,          /* NV_f_p only */
    FP_OPCODE_X2D,            /* NV_f_p only - 2d mat mul */
    FP_OPCODE_XPD,            /* ARB_f_p only - cross product */
+   FP_OPCODE_PRINT,          /* Mesa only */
    FP_OPCODE_END /* private opcode */
 };
 
@@ -158,6 +159,7 @@ struct fp_instruction
 #if FEATURE_MESA_program_debug
    GLint StringPos;
 #endif
+   void *Data;  /* some arbitrary data, only used for PRINT instruction now */
 };
 
 
index e84cf9d50499bcaf75b5fd3f2755181f145c530a..b02143a2e6660718244714f69f99c3a031762db7 100644 (file)
@@ -1402,7 +1402,7 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
       program->IsPositionInvariant = parseState.isPositionInvariant;
       program->IsNVProgram = GL_TRUE;
 
-#ifdef DEBUG
+#ifdef DEBUG_foo
       _mesa_printf("--- glLoadProgramNV result ---\n");
       _mesa_print_nv_vertex_program(program);
       _mesa_printf("------------------------------\n");
index ca0421181cedae68eb533fabb35c6ed438761c2b..307736f79ca13a9f68a7b5d9521bb80622276632 100644 (file)
@@ -278,8 +278,14 @@ _mesa_delete_program(GLcontext *ctx, struct program *prog)
    else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
             prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
       struct fragment_program *fprog = (struct fragment_program *) prog;
-      if (fprog->Instructions)
+      if (fprog->Instructions) {
+         GLuint i;
+         for (i = 0; i < fprog->Base.NumInstructions; i++) {
+            if (fprog->Instructions[i].Data)
+               _mesa_free(fprog->Instructions[i].Data);
+         }
          _mesa_free(fprog->Instructions);
+      }
       if (fprog->Parameters)
          _mesa_free_parameter_list(fprog->Parameters);
    }
index d083f83645d1d87326dc6404203389ceae0ba823..5d9979c5c62d6a36eecb749d7799eec6b28eb947 100644 (file)
@@ -120,6 +120,11 @@ get_register_pointer( GLcontext *ctx,
          ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
          src = machine->Inputs[source->Index];
          break;
+      case PROGRAM_OUTPUT:
+         /* This is only for PRINT */
+         ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
+         src = machine->Outputs[source->Index];
+         break;
       case PROGRAM_LOCAL_PARAM:
          ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
          src = program->Base.LocalParams[source->Index];
@@ -128,10 +133,8 @@ get_register_pointer( GLcontext *ctx,
          ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_PARAMS);
          src = ctx->FragmentProgram.Parameters[source->Index];
          break;
-
       case PROGRAM_STATE_VAR:
-                       /* Fallthrough */
-
+         /* Fallthrough */
       case PROGRAM_NAMED_PARAM:
          ASSERT(source->Index < (GLint) program->Parameters->NumParameters);
          src = program->Parameters->Parameters[source->Index].Values;
@@ -342,7 +345,7 @@ fetch_vector1( GLcontext *ctx,
 }
 
 
-/*
+/**
  * Test value against zero and return GT, LT, EQ or UN if NaN.
  */
 static INLINE GLuint
@@ -357,7 +360,8 @@ generate_cc( float value )
    return COND_EQ;
 }
 
-/*
+
+/**
  * Test if the ccMaskRule is satisfied by the given condition code.
  * Used to mask destination writes according to the current condition codee.
  */
@@ -1306,6 +1310,19 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, result );
             }
             break;
+         case FP_OPCODE_PRINT:
+            {
+               if (inst->SrcReg[0].File != -1) {
+                  GLfloat a[4];
+                  fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a);
+                  _mesa_printf("%s%g, %g, %g, %g\n", (const char *) inst->Data,
+                               a[0], a[1], a[2], a[3]);
+               }
+               else {
+                  _mesa_printf("%s\n", (const char *) inst->Data);
+               }
+            }
+            break;
          case FP_OPCODE_END:
             return GL_TRUE;
          default: