summaryrefslogtreecommitdiff
path: root/src/mesa/shader/arbprogparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/arbprogparse.c')
-rw-r--r--src/mesa/shader/arbprogparse.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index 39988b5fca..536404bf97 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -30,6 +30,27 @@
* \author Karl Rasche
*/
+/**
+Notes on program parameters, etc.
+
+The instructions we emit will use six kinds of source registers:
+
+ PROGRAM_INPUT - input registers
+ PROGRAM_TEMPORARY - temp registers
+ PROGRAM_ADDRESS - address/indirect register
+ PROGRAM_SAMPLER - texture sampler
+ PROGRAM_CONSTANT - indexes into program->Parameters, a known constant/literal
+ PROGRAM_STATE_VAR - indexes into program->Parameters, and may actually be:
+ + a state variable, like "state.fog.color", or
+ + a pointer to a "program.local[k]" parameter, or
+ + a pointer to a "program.env[k]" parameter
+
+Basically, all the program.local[] and program.env[] values will get mapped
+into the unified gl_program->Parameters array. This solves the problem of
+having three separate program parameter arrays.
+*/
+
+
#include "main/glheader.h"
#include "main/imports.h"
#include "main/context.h"
@@ -38,16 +59,11 @@
#include "shader/grammar/grammar_mesa.h"
#include "arbprogparse.h"
#include "program.h"
+#include "programopt.h"
#include "prog_parameter.h"
#include "prog_statevars.h"
#include "prog_instruction.h"
-
-/* For ARB programs, use the NV instruction limits */
-#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
- MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
-
-
/**
* This is basically a union of the vertex_program and fragment_program
* structs that we can use to parse the program into
@@ -1870,7 +1886,11 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
const_values, 4);
if (param_var->param_binding_begin == ~0U)
param_var->param_binding_begin = idx;
- param_var->param_binding_type = PROGRAM_CONSTANT;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+ /* Note: when we reference this parameter in an instruction later,
+ * we'll check if it's really a constant/immediate and set the
+ * instruction register type appropriately.
+ */
param_var->param_binding_length++;
Program->Base.NumParameters++;
break;
@@ -2577,6 +2597,18 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
return 1;
}
+ if (*File == PROGRAM_STATE_VAR) {
+ enum register_file file;
+
+ /* If we're referencing the Program->Parameters[] array, check if the
+ * parameter is really a constant/literal. If so, set File to CONSTANT.
+ */
+ assert(*Index < (GLint) Program->Base.Parameters->NumParameters);
+ file = Program->Base.Parameters->Parameters[*Index].Type;
+ if (file == PROGRAM_CONSTANT)
+ *File = PROGRAM_CONSTANT;
+ }
+
/* Add attributes to InputsRead only if they are used the program.
* This avoids the handling of unused ATTRIB declarations in the drivers. */
if (*File == PROGRAM_INPUT)
@@ -3353,11 +3385,11 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
fprintf (stderr, "%s\n",
Program->Base.Parameters->Parameters[a + b].Name);
if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
- const char *s;
+ char *s;
s = _mesa_program_state_string(Program->Base.Parameters->Parameters
[a + b].StateIndexes);
fprintf(stderr, "%s\n", s);
- _mesa_free((char *) s);
+ _mesa_free(s);
}
else
fprintf (stderr, "%f %f %f %f\n",
@@ -3405,7 +3437,7 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst,
: ctx->Const.VertexProgram.MaxInstructions;
GLint err = 0;
- ASSERT(MAX_INSTRUCTIONS >= maxInst);
+ ASSERT(MAX_PROGRAM_INSTRUCTIONS >= maxInst);
Program->MajorVersion = (GLuint) * inst++;
Program->MinorVersion = (GLuint) * inst++;
@@ -3760,7 +3792,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
/* Initialize the arb_program struct */
program->Base.String = strz;
- program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
+ program->Base.Instructions = _mesa_alloc_instructions(MAX_PROGRAM_INSTRUCTIONS);
program->Base.NumInstructions =
program->Base.NumTemporaries =
program->Base.NumParameters =
@@ -3805,12 +3837,12 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
_mesa_free (parsed);
- /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
+ /* Reallocate the instruction array from size [MAX_PROGRAM_INSTRUCTIONS]
* to size [ap.Base.NumInstructions].
*/
program->Base.Instructions
= _mesa_realloc_instructions(program->Base.Instructions,
- MAX_INSTRUCTIONS,
+ MAX_PROGRAM_INSTRUCTIONS,
program->Base.NumInstructions);
return !err;
@@ -3874,6 +3906,16 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
_mesa_free_parameter_list(program->Base.Parameters);
program->Base.Parameters = ap.Base.Parameters;
+ /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
+ * or similar. We used to leave this up to drivers, but it appears
+ * there's no hardware that wants to do fog in a discrete stage separate
+ * from the fragment shader.
+ */
+ if (program->FogOption != GL_NONE) {
+ _mesa_append_fog_code(ctx, program);
+ program->FogOption = GL_NONE;
+ }
+
#if DEBUG_FP
_mesa_printf("____________Fragment program %u ________\n", program->Base.Id);
_mesa_print_program(&program->Base);