summaryrefslogtreecommitdiff
path: root/src/mesa/program
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/arbprogparse.c4
-rw-r--r--src/mesa/program/arbprogparse.h4
-rw-r--r--src/mesa/program/ir_to_mesa.cpp478
-rw-r--r--src/mesa/program/ir_to_mesa.h8
-rw-r--r--src/mesa/program/nvfragparse.c4
-rw-r--r--src/mesa/program/nvfragparse.h2
-rw-r--r--src/mesa/program/nvvertparse.c4
-rw-r--r--src/mesa/program/nvvertparse.h2
-rw-r--r--src/mesa/program/prog_cache.c6
-rw-r--r--src/mesa/program/prog_cache.h4
-rw-r--r--src/mesa/program/prog_execute.c6
-rw-r--r--src/mesa/program/prog_execute.h8
-rw-r--r--src/mesa/program/prog_optimize.c4
-rw-r--r--src/mesa/program/prog_optimize.h2
-rw-r--r--src/mesa/program/prog_parameter.c15
-rw-r--r--src/mesa/program/prog_print.c4
-rw-r--r--src/mesa/program/prog_print.h2
-rw-r--r--src/mesa/program/prog_statevars.c35
-rw-r--r--src/mesa/program/prog_statevars.h7
-rw-r--r--src/mesa/program/program.c30
-rw-r--r--src/mesa/program/program.h40
-rw-r--r--src/mesa/program/program_parse.tab.c2
-rw-r--r--src/mesa/program/program_parse.y2
-rw-r--r--src/mesa/program/program_parser.h9
-rw-r--r--src/mesa/program/programopt.c12
-rw-r--r--src/mesa/program/programopt.h8
-rw-r--r--src/mesa/program/register_allocate.c361
-rw-r--r--src/mesa/program/register_allocate.h69
-rw-r--r--src/mesa/program/sampler.cpp140
-rw-r--r--src/mesa/program/sampler.h29
30 files changed, 811 insertions, 490 deletions
diff --git a/src/mesa/program/arbprogparse.c b/src/mesa/program/arbprogparse.c
index f834aaf568..ca63e72c08 100644
--- a/src/mesa/program/arbprogparse.c
+++ b/src/mesa/program/arbprogparse.c
@@ -64,7 +64,7 @@ having three separate program parameter arrays.
void
-_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
+_mesa_parse_arb_fragment_program(struct gl_context* ctx, GLenum target,
const GLvoid *str, GLsizei len,
struct gl_fragment_program *program)
{
@@ -162,7 +162,7 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
* object unchanged.
*/
void
-_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
+_mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target,
const GLvoid *str, GLsizei len,
struct gl_vertex_program *program)
{
diff --git a/src/mesa/program/arbprogparse.h b/src/mesa/program/arbprogparse.h
index 980d39fb9f..08e25a1c16 100644
--- a/src/mesa/program/arbprogparse.h
+++ b/src/mesa/program/arbprogparse.h
@@ -29,12 +29,12 @@
#include "main/mtypes.h"
extern void
-_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
+_mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target,
const GLvoid *str, GLsizei len,
struct gl_vertex_program *program);
extern void
-_mesa_parse_arb_fragment_program(GLcontext *ctx, GLenum target,
+_mesa_parse_arb_fragment_program(struct gl_context *ctx, GLenum target,
const GLvoid *str, GLsizei len,
struct gl_fragment_program *program);
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index f24dce79f6..bdd3fd92ff 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -26,8 +26,7 @@
/**
* \file ir_to_mesa.cpp
*
- * Translates the IR to ARB_fragment_program text if possible,
- * printing the result
+ * Translate GLSL IR to Mesa's gl_program representation.
*/
#include <stdio.h>
@@ -54,6 +53,7 @@ extern "C" {
#include "program/program.h"
#include "program/prog_uniform.h"
#include "program/prog_parameter.h"
+#include "program/sampler.h"
}
static int swizzle_for_size(int size);
@@ -183,7 +183,7 @@ public:
function_entry *current_function;
- GLcontext *ctx;
+ struct gl_context *ctx;
struct gl_program *prog;
struct gl_shader_program *shader_program;
struct gl_shader_compiler_options *options;
@@ -274,8 +274,6 @@ public:
GLboolean try_emit_mad(ir_expression *ir,
int mul_operand);
- int get_sampler_uniform_value(ir_dereference *deref);
-
void *mem_ctx;
};
@@ -289,19 +287,22 @@ ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
};
-static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
+static void
+fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
-static void fail_link(struct gl_shader_program *prog, const char *fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args);
- va_end(args);
+static void
+fail_link(struct gl_shader_program *prog, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args);
+ va_end(args);
- prog->LinkStatus = GL_FALSE;
- }
+ prog->LinkStatus = GL_FALSE;
+}
-static int swizzle_for_size(int size)
+static int
+swizzle_for_size(int size)
{
int size_swizzles[4] = {
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
@@ -310,6 +311,7 @@ static int swizzle_for_size(int size)
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
};
+ assert((size >= 1) && (size <= 4));
return size_swizzles[size - 1];
}
@@ -578,243 +580,6 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
return NULL;
}
-struct statevar_element {
- const char *field;
- int tokens[STATE_LENGTH];
- int swizzle;
-};
-
-static struct statevar_element gl_DepthRange_elements[] = {
- {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
- {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
- {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
-};
-
-static struct statevar_element gl_ClipPlane_elements[] = {
- {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
-};
-
-static struct statevar_element gl_Point_elements[] = {
- {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
- {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
- {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
- {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
- {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
- {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
- {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
-};
-
-static struct statevar_element gl_FrontMaterial_elements[] = {
- {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
- {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
- {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
-};
-
-static struct statevar_element gl_BackMaterial_elements[] = {
- {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
- {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
- {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
-};
-
-static struct statevar_element gl_LightSource_elements[] = {
- {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
- {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
- {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
- {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW},
- {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
- {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
- {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
- {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
- {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
- {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
-};
-
-static struct statevar_element gl_LightModel_elements[] = {
- {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_FrontLightModelProduct_elements[] = {
- {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_BackLightModelProduct_elements[] = {
- {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_FrontLightProduct_elements[] = {
- {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_BackLightProduct_elements[] = {
- {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_TextureEnvColor_elements[] = {
- {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneS_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneT_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneR_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_EyePlaneQ_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneS_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneT_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneR_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_ObjectPlaneQ_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
-};
-
-static struct statevar_element gl_Fog_elements[] = {
- {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
- {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
- {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
- {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
- {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
-};
-
-static struct statevar_element gl_NormalScale_elements[] = {
- {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
-};
-
-#define MATRIX(name, statevar, modifier) \
- static struct statevar_element name ## _elements[] = { \
- { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
- { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \
- { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \
- { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \
- }
-
-MATRIX(gl_ModelViewMatrix,
- STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ModelViewMatrixInverse,
- STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ModelViewMatrixTranspose,
- STATE_MODELVIEW_MATRIX, 0);
-MATRIX(gl_ModelViewMatrixInverseTranspose,
- STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_ProjectionMatrix,
- STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ProjectionMatrixInverse,
- STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ProjectionMatrixTranspose,
- STATE_PROJECTION_MATRIX, 0);
-MATRIX(gl_ProjectionMatrixInverseTranspose,
- STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_ModelViewProjectionMatrix,
- STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ModelViewProjectionMatrixInverse,
- STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ModelViewProjectionMatrixTranspose,
- STATE_MVP_MATRIX, 0);
-MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
- STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_TextureMatrix,
- STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_TextureMatrixInverse,
- STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_TextureMatrixTranspose,
- STATE_TEXTURE_MATRIX, 0);
-MATRIX(gl_TextureMatrixInverseTranspose,
- STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
-
-static struct statevar_element gl_NormalMatrix_elements[] = {
- { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
- SWIZZLE_XYZW },
- { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
- SWIZZLE_XYZW },
- { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
- SWIZZLE_XYZW },
-};
-
-#undef MATRIX
-
-#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
-
-static const struct statevar {
- const char *name;
- struct statevar_element *elements;
- unsigned int num_elements;
-} statevars[] = {
- STATEVAR(gl_DepthRange),
- STATEVAR(gl_ClipPlane),
- STATEVAR(gl_Point),
- STATEVAR(gl_FrontMaterial),
- STATEVAR(gl_BackMaterial),
- STATEVAR(gl_LightSource),
- STATEVAR(gl_LightModel),
- STATEVAR(gl_FrontLightModelProduct),
- STATEVAR(gl_BackLightModelProduct),
- STATEVAR(gl_FrontLightProduct),
- STATEVAR(gl_BackLightProduct),
- STATEVAR(gl_TextureEnvColor),
- STATEVAR(gl_EyePlaneS),
- STATEVAR(gl_EyePlaneT),
- STATEVAR(gl_EyePlaneR),
- STATEVAR(gl_EyePlaneQ),
- STATEVAR(gl_ObjectPlaneS),
- STATEVAR(gl_ObjectPlaneT),
- STATEVAR(gl_ObjectPlaneR),
- STATEVAR(gl_ObjectPlaneQ),
- STATEVAR(gl_Fog),
-
- STATEVAR(gl_ModelViewMatrix),
- STATEVAR(gl_ModelViewMatrixInverse),
- STATEVAR(gl_ModelViewMatrixTranspose),
- STATEVAR(gl_ModelViewMatrixInverseTranspose),
-
- STATEVAR(gl_ProjectionMatrix),
- STATEVAR(gl_ProjectionMatrixInverse),
- STATEVAR(gl_ProjectionMatrixTranspose),
- STATEVAR(gl_ProjectionMatrixInverseTranspose),
-
- STATEVAR(gl_ModelViewProjectionMatrix),
- STATEVAR(gl_ModelViewProjectionMatrixInverse),
- STATEVAR(gl_ModelViewProjectionMatrixTranspose),
- STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
-
- STATEVAR(gl_TextureMatrix),
- STATEVAR(gl_TextureMatrixInverse),
- STATEVAR(gl_TextureMatrixTranspose),
- STATEVAR(gl_TextureMatrixInverseTranspose),
-
- STATEVAR(gl_NormalMatrix),
- STATEVAR(gl_NormalScale),
-};
-
void
ir_to_mesa_visitor::visit(ir_variable *ir)
{
@@ -827,19 +592,20 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
unsigned int i;
+ const struct gl_builtin_uniform_desc *statevar;
- for (i = 0; i < Elements(statevars); i++) {
- if (strcmp(ir->name, statevars[i].name) == 0)
+ for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
+ if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
break;
}
- if (i == Elements(statevars)) {
+ if (!_mesa_builtin_uniform_desc[i].name) {
fail_link(this->shader_program,
"Failed to find builtin uniform `%s'\n", ir->name);
return;
}
- const struct statevar *statevar = &statevars[i];
+ statevar = &_mesa_builtin_uniform_desc[i];
int array_count;
if (ir->type->is_array()) {
@@ -882,7 +648,7 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
for (int a = 0; a < array_count; a++) {
for (unsigned int i = 0; i < statevar->num_elements; i++) {
- struct statevar_element *element = &statevar->elements[i];
+ struct gl_builtin_uniform_element *element = &statevar->elements[i];
int tokens[STATE_LENGTH];
memcpy(tokens, element->tokens, sizeof(element->tokens));
@@ -1096,6 +862,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
assert(!ir->operands[operand]->type->is_matrix());
}
+ int vector_elements = ir->operands[0]->type->vector_elements;
+ if (ir->operands[1]) {
+ vector_elements = MAX2(vector_elements,
+ ir->operands[1]->type->vector_elements);
+ }
+
this->result.file = PROGRAM_UNDEFINED;
/* Storage for our result. Ideally for an assignment we'd be using
@@ -1204,7 +976,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
ir_to_mesa_emit_op2(ir, OPCODE_SNE,
ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
- ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp);
+ if (vector_elements == 4)
+ ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp);
+ else if (vector_elements == 3)
+ ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, temp, temp);
+ else
+ ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, temp, temp);
ir_to_mesa_emit_op2(ir, OPCODE_SEQ,
result_dst, result_src, src_reg_for_float(0.0));
} else {
@@ -1218,7 +995,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
ir_to_mesa_emit_op2(ir, OPCODE_SNE,
ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
- ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp);
+ if (vector_elements == 4)
+ ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp);
+ else if (vector_elements == 3)
+ ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, temp, temp);
+ else
+ ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, temp, temp);
ir_to_mesa_emit_op2(ir, OPCODE_SNE,
result_dst, result_src, src_reg_for_float(0.0));
} else {
@@ -1348,6 +1130,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
case ir_binop_bit_and:
case ir_binop_bit_xor:
case ir_binop_bit_or:
+ case ir_unop_round_even:
assert(!"GLSL 1.30 features unsupported");
break;
}
@@ -1577,13 +1360,39 @@ ir_to_mesa_visitor::visit(ir_assignment *ir)
assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
l.writemask = WRITEMASK_XYZW;
} else if (ir->lhs->type->is_scalar()) {
- /* FINISHME: This hack makes writing to gl_FragData, which lives in the
+ /* FINISHME: This hack makes writing to gl_FragDepth, which lives in the
* FINISHME: W component of fragment shader output zero, work correctly.
*/
l.writemask = WRITEMASK_XYZW;
} else {
+ int swizzles[4];
+ int first_enabled_chan = 0;
+ int rhs_chan = 0;
+
assert(ir->lhs->type->is_vector());
l.writemask = ir->write_mask;
+
+ for (int i = 0; i < 4; i++) {
+ if (l.writemask & (1 << i)) {
+ first_enabled_chan = GET_SWZ(r.swizzle, i);
+ break;
+ }
+ }
+
+ /* Swizzle a small RHS vector into the channels being written.
+ *
+ * glsl ir treats write_mask as dictating how many channels are
+ * present on the RHS while Mesa IR treats write_mask as just
+ * showing which channels of the vec4 RHS get written.
+ */
+ for (int i = 0; i < 4; i++) {
+ if (l.writemask & (1 << i))
+ swizzles[i] = GET_SWZ(r.swizzle, rhs_chan++);
+ else
+ swizzles[i] = first_enabled_chan;
+ }
+ r.swizzle = MAKE_SWIZZLE4(swizzles[0], swizzles[1],
+ swizzles[2], swizzles[3]);
}
assert(l.file != PROGRAM_UNDEFINED);
@@ -1852,89 +1661,6 @@ ir_to_mesa_visitor::visit(ir_call *ir)
this->result = entry->return_reg;
}
-class get_sampler_name : public ir_hierarchical_visitor
-{
-public:
- get_sampler_name(ir_to_mesa_visitor *mesa, ir_dereference *last)
- {
- this->mem_ctx = mesa->mem_ctx;
- this->mesa = mesa;
- this->name = NULL;
- this->offset = 0;
- this->last = last;
- }
-
- virtual ir_visitor_status visit(ir_dereference_variable *ir)
- {
- this->name = ir->var->name;
- return visit_continue;
- }
-
- virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
- {
- this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
- return visit_continue;
- }
-
- virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
- {
- ir_constant *index = ir->array_index->as_constant();
- int i;
-
- if (index) {
- i = index->value.i[0];
- } else {
- /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
- * while GLSL 1.30 requires that the array indices be
- * constant integer expressions. We don't expect any driver
- * to actually work with a really variable array index, so
- * all that would work would be an unrolled loop counter that ends
- * up being constant above.
- */
- mesa->shader_program->InfoLog =
- talloc_asprintf_append(mesa->shader_program->InfoLog,
- "warning: Variable sampler array index "
- "unsupported.\nThis feature of the language "
- "was removed in GLSL 1.20 and is unlikely "
- "to be supported for 1.10 in Mesa.\n");
- i = 0;
- }
- if (ir != last) {
- this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i);
- } else {
- offset = i;
- }
- return visit_continue;
- }
-
- ir_to_mesa_visitor *mesa;
- const char *name;
- void *mem_ctx;
- int offset;
- ir_dereference *last;
-};
-
-int
-ir_to_mesa_visitor::get_sampler_uniform_value(ir_dereference *sampler)
-{
- get_sampler_name getname(this, sampler);
-
- sampler->accept(&getname);
-
- GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
- getname.name);
-
- if (index < 0) {
- fail_link(this->shader_program,
- "failed to find sampler named %s.\n", getname.name);
- return 0;
- }
-
- index += getname.offset;
-
- return this->prog->Parameters->ParameterValues[index][0];
-}
-
void
ir_to_mesa_visitor::visit(ir_texture *ir)
{
@@ -2034,7 +1760,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
if (ir->shadow_comparitor)
inst->tex_shadow = GL_TRUE;
- inst->sampler = get_sampler_uniform_value(ir->sampler);
+ inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler,
+ this->shader_program,
+ this->prog);
const glsl_type *sampler_type = ir->sampler->type;
@@ -2435,7 +2163,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
}
static void
-set_uniform_initializer(GLcontext *ctx, void *mem_ctx,
+set_uniform_initializer(struct gl_context *ctx, void *mem_ctx,
struct gl_shader_program *shader_program,
const char *name, const glsl_type *type,
ir_constant *val)
@@ -2505,13 +2233,17 @@ set_uniform_initializer(GLcontext *ctx, void *mem_ctx,
}
static void
-set_uniform_initializers(GLcontext *ctx,
+set_uniform_initializers(struct gl_context *ctx,
struct gl_shader_program *shader_program)
{
void *mem_ctx = NULL;
- for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) {
+ for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
struct gl_shader *shader = shader_program->_LinkedShaders[i];
+
+ if (shader == NULL)
+ continue;
+
foreach_iter(exec_list_iterator, iter, *shader->ir) {
ir_instruction *ir = (ir_instruction *)iter.get();
ir_variable *var = ir->as_variable();
@@ -2530,8 +2262,12 @@ set_uniform_initializers(GLcontext *ctx,
talloc_free(mem_ctx);
}
+
+/**
+ * Convert a shader's GLSL IR into a Mesa gl_program.
+ */
struct gl_program *
-get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
+get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program,
struct gl_shader *shader)
{
ir_to_mesa_visitor v;
@@ -2620,10 +2356,12 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *,
num_instructions);
+ /* Convert ir_mesa_instructions into prog_instructions.
+ */
mesa_inst = mesa_instructions;
i = 0;
foreach_iter(exec_list_iterator, iter, v.instructions) {
- ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
+ const ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
mesa_inst->Opcode = inst->op;
mesa_inst->CondUpdate = inst->cond_update;
@@ -2644,6 +2382,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
if (mesa_inst->DstReg.RelAddr)
prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File;
+ /* Update program's bitmask of indirectly accessed register files */
for (unsigned src = 0; src < 3; src++)
if (mesa_inst->SrcReg[src].RelAddr)
prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File;
@@ -2705,8 +2444,14 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
}
extern "C" {
+
+/**
+ * Called via ctx->Driver.CompilerShader().
+ * This is a no-op.
+ * XXX can we remove the ctx->Driver.CompileShader() hook?
+ */
GLboolean
-_mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+_mesa_ir_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
assert(shader->CompileStatus);
(void) ctx;
@@ -2714,15 +2459,25 @@ _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader)
return GL_TRUE;
}
+
+/**
+ * Link a shader.
+ * Called via ctx->Driver.LinkShader()
+ * This actually involves converting GLSL IR into Mesa gl_programs with
+ * code lowering and other optimizations.
+ */
GLboolean
-_mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+_mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
{
assert(prog->LinkStatus);
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
bool progress;
exec_list *ir = prog->_LinkedShaders[i]->ir;
- struct gl_shader_compiler_options *options =
+ const struct gl_shader_compiler_options *options =
&ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(prog->_LinkedShaders[i]->Type)];
do {
@@ -2763,10 +2518,13 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
validate_ir_tree(ir);
}
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
struct gl_program *linked_prog;
bool ok = true;
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
switch (prog->_LinkedShaders[i]->Type) {
@@ -2792,8 +2550,12 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
return GL_TRUE;
}
+
+/**
+ * Compile a GLSL shader. Called via glCompileShader().
+ */
void
-_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
struct _mesa_glsl_parse_state *state =
new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
@@ -2876,8 +2638,12 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
}
}
+
+/**
+ * Link a GLSL shader program. Called via glLinkProgram().
+ */
void
-_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+_mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
{
unsigned int i;
diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h
index ecaacde4bb..7197615f94 100644
--- a/src/mesa/program/ir_to_mesa.h
+++ b/src/mesa/program/ir_to_mesa.h
@@ -28,10 +28,10 @@ extern "C" {
#include "main/config.h"
#include "main/mtypes.h"
-void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh);
-void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
-GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader);
-GLboolean _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
+void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *sh);
+void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);
+GLboolean _mesa_ir_compile_shader(struct gl_context *ctx, struct gl_shader *shader);
+GLboolean _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);
#ifdef __cplusplus
}
diff --git a/src/mesa/program/nvfragparse.c b/src/mesa/program/nvfragparse.c
index 0de3c5804d..8516b5fc1f 100644
--- a/src/mesa/program/nvfragparse.c
+++ b/src/mesa/program/nvfragparse.c
@@ -141,7 +141,7 @@ static const struct instruction_pattern Instructions[] = {
* _successfully_ parsed the program text.
*/
struct parse_state {
- GLcontext *ctx;
+ struct gl_context *ctx;
const GLubyte *start; /* start of program string */
const GLubyte *pos; /* current position */
const GLubyte *curLine;
@@ -1463,7 +1463,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
* indicates the position of the error in 'str'.
*/
void
-_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
+_mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum dstTarget,
const GLubyte *str, GLsizei len,
struct gl_fragment_program *program)
{
diff --git a/src/mesa/program/nvfragparse.h b/src/mesa/program/nvfragparse.h
index e28a6c4934..3e85dd2c30 100644
--- a/src/mesa/program/nvfragparse.h
+++ b/src/mesa/program/nvfragparse.h
@@ -33,7 +33,7 @@
#include "main/mtypes.h"
extern void
-_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum target,
+_mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum target,
const GLubyte *str, GLsizei len,
struct gl_fragment_program *program);
diff --git a/src/mesa/program/nvvertparse.c b/src/mesa/program/nvvertparse.c
index 1ac83d0e59..bdd44a4513 100644
--- a/src/mesa/program/nvvertparse.c
+++ b/src/mesa/program/nvvertparse.c
@@ -54,7 +54,7 @@
* program attributes.
*/
struct parse_state {
- GLcontext *ctx;
+ struct gl_context *ctx;
const GLubyte *start;
const GLubyte *pos;
const GLubyte *curLine;
@@ -1282,7 +1282,7 @@ Parse_Program(struct parse_state *parseState,
* indicates the position of the error in 'str'.
*/
void
-_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
+_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum dstTarget,
const GLubyte *str, GLsizei len,
struct gl_vertex_program *program)
{
diff --git a/src/mesa/program/nvvertparse.h b/src/mesa/program/nvvertparse.h
index 91ef79e6c3..e98e867320 100644
--- a/src/mesa/program/nvvertparse.h
+++ b/src/mesa/program/nvvertparse.h
@@ -32,7 +32,7 @@
#include "main/mtypes.h"
extern void
-_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum target,
+_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum target,
const GLubyte *str, GLsizei len,
struct gl_vertex_program *program);
diff --git a/src/mesa/program/prog_cache.c b/src/mesa/program/prog_cache.c
index 8af689754b..56ca59890d 100644
--- a/src/mesa/program/prog_cache.c
+++ b/src/mesa/program/prog_cache.c
@@ -104,7 +104,7 @@ rehash(struct gl_program_cache *cache)
static void
-clear_cache(GLcontext *ctx, struct gl_program_cache *cache)
+clear_cache(struct gl_context *ctx, struct gl_program_cache *cache)
{
struct cache_item *c, *next;
GLuint i;
@@ -145,7 +145,7 @@ _mesa_new_program_cache(void)
void
-_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *cache)
+_mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *cache)
{
clear_cache(ctx, cache);
free(cache->items);
@@ -178,7 +178,7 @@ _mesa_search_program_cache(struct gl_program_cache *cache,
void
-_mesa_program_cache_insert(GLcontext *ctx,
+_mesa_program_cache_insert(struct gl_context *ctx,
struct gl_program_cache *cache,
const void *key, GLuint keysize,
struct gl_program *program)
diff --git a/src/mesa/program/prog_cache.h b/src/mesa/program/prog_cache.h
index bfe8f99d44..4907ae3030 100644
--- a/src/mesa/program/prog_cache.h
+++ b/src/mesa/program/prog_cache.h
@@ -41,7 +41,7 @@ extern struct gl_program_cache *
_mesa_new_program_cache(void);
extern void
-_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *pc);
+_mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *pc);
extern struct gl_program *
@@ -49,7 +49,7 @@ _mesa_search_program_cache(struct gl_program_cache *cache,
const void *key, GLuint keysize);
extern void
-_mesa_program_cache_insert(GLcontext *ctx,
+_mesa_program_cache_insert(struct gl_context *ctx,
struct gl_program_cache *cache,
const void *key, GLuint keysize,
struct gl_program *program);
diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c
index 2ae5bc572a..1d97a077f5 100644
--- a/src/mesa/program/prog_execute.c
+++ b/src/mesa/program/prog_execute.c
@@ -296,7 +296,7 @@ fetch_vector4ui(const struct prog_src_register *source,
* XXX this currently only works for fragment program input attribs.
*/
static void
-fetch_vector4_deriv(GLcontext * ctx,
+fetch_vector4_deriv(struct gl_context * ctx,
const struct prog_src_register *source,
const struct gl_program_machine *machine,
char xOrY, GLfloat result[4])
@@ -380,7 +380,7 @@ fetch_vector1ui(const struct prog_src_register *source,
* Fetch texel from texture. Use partial derivatives when possible.
*/
static INLINE void
-fetch_texel(GLcontext *ctx,
+fetch_texel(struct gl_context *ctx,
const struct gl_program_machine *machine,
const struct prog_instruction *inst,
const GLfloat texcoord[4], GLfloat lodBias,
@@ -630,7 +630,7 @@ store_vector4ui(const struct prog_instruction *inst,
* \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
*/
GLboolean
-_mesa_execute_program(GLcontext * ctx,
+_mesa_execute_program(struct gl_context * ctx,
const struct gl_program *program,
struct gl_program_machine *machine)
{
diff --git a/src/mesa/program/prog_execute.h b/src/mesa/program/prog_execute.h
index f59b65176f..cefd468c36 100644
--- a/src/mesa/program/prog_execute.h
+++ b/src/mesa/program/prog_execute.h
@@ -29,10 +29,10 @@
#include "main/mtypes.h"
-typedef void (*FetchTexelLodFunc)(GLcontext *ctx, const GLfloat texcoord[4],
+typedef void (*FetchTexelLodFunc)(struct gl_context *ctx, const GLfloat texcoord[4],
GLfloat lambda, GLuint unit, GLfloat color[4]);
-typedef void (*FetchTexelDerivFunc)(GLcontext *ctx, const GLfloat texcoord[4],
+typedef void (*FetchTexelDerivFunc)(struct gl_context *ctx, const GLfloat texcoord[4],
const GLfloat texdx[4],
const GLfloat texdy[4],
GLfloat lodBias,
@@ -74,11 +74,11 @@ struct gl_program_machine
extern void
-_mesa_get_program_register(GLcontext *ctx, gl_register_file file,
+_mesa_get_program_register(struct gl_context *ctx, gl_register_file file,
GLuint index, GLfloat val[4]);
extern GLboolean
-_mesa_execute_program(GLcontext *ctx,
+_mesa_execute_program(struct gl_context *ctx,
const struct gl_program *program,
struct gl_program_machine *machine);
diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c
index 0dc779073d..96971f2eda 100644
--- a/src/mesa/program/prog_optimize.c
+++ b/src/mesa/program/prog_optimize.c
@@ -1216,7 +1216,7 @@ _mesa_reallocate_registers(struct gl_program *prog)
#if 0
static void
-print_it(GLcontext *ctx, struct gl_program *program, const char *txt) {
+print_it(struct gl_context *ctx, struct gl_program *program, const char *txt) {
fprintf(stderr, "%s (%u inst):\n", txt, program->NumInstructions);
_mesa_print_program(program);
_mesa_print_program_parameters(ctx, program);
@@ -1230,7 +1230,7 @@ print_it(GLcontext *ctx, struct gl_program *program, const char *txt) {
* instructions, temp regs, etc.
*/
void
-_mesa_optimize_program(GLcontext *ctx, struct gl_program *program)
+_mesa_optimize_program(struct gl_context *ctx, struct gl_program *program)
{
GLboolean any_change;
diff --git a/src/mesa/program/prog_optimize.h b/src/mesa/program/prog_optimize.h
index 06cd9cb2c2..00f1080449 100644
--- a/src/mesa/program/prog_optimize.h
+++ b/src/mesa/program/prog_optimize.h
@@ -41,6 +41,6 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions,
GLint intEnd[MAX_PROGRAM_TEMPS]);
extern void
-_mesa_optimize_program(GLcontext *ctx, struct gl_program *program);
+_mesa_optimize_program(struct gl_context *ctx, struct gl_program *program);
#endif
diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c
index 6bf8a081b0..3570cab118 100644
--- a/src/mesa/program/prog_parameter.c
+++ b/src/mesa/program/prog_parameter.c
@@ -378,18 +378,9 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
/* Check if the state reference is already in the list */
for (index = 0; index < (GLint) paramList->NumParameters; index++) {
- GLuint i, match = 0;
- for (i = 0; i < STATE_LENGTH; i++) {
- if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) {
- match++;
- }
- else {
- break;
- }
- }
- if (match == STATE_LENGTH) {
- /* this state reference is already in the parameter list */
- return index;
+ if (!memcmp(paramList->Parameters[index].StateIndexes,
+ stateTokens, STATE_LENGTH * sizeof(gl_state_index))) {
+ return index;
}
}
diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c
index 00aa6de963..79c01020eb 100644
--- a/src/mesa/program/prog_print.c
+++ b/src/mesa/program/prog_print.c
@@ -909,7 +909,7 @@ binary(GLbitfield64 val)
*/
static void
_mesa_fprint_program_parameters(FILE *f,
- GLcontext *ctx,
+ struct gl_context *ctx,
const struct gl_program *prog)
{
GLuint i;
@@ -951,7 +951,7 @@ _mesa_fprint_program_parameters(FILE *f,
* Print all of a program's parameters/fields to stderr.
*/
void
-_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog)
+_mesa_print_program_parameters(struct gl_context *ctx, const struct gl_program *prog)
{
_mesa_fprint_program_parameters(stderr, ctx, prog);
}
diff --git a/src/mesa/program/prog_print.h b/src/mesa/program/prog_print.h
index 78b90aeb4d..f080b3fd2e 100644
--- a/src/mesa/program/prog_print.h
+++ b/src/mesa/program/prog_print.h
@@ -100,7 +100,7 @@ _mesa_fprint_program_opt(FILE *f,
GLboolean lineNumbers);
extern void
-_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog);
+_mesa_print_program_parameters(struct gl_context *ctx, const struct gl_program *prog);
extern void
_mesa_print_parameter_list(const struct gl_program_parameter_list *list);
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index 2687f8ae2c..baac29ff0d 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -46,7 +46,7 @@
* The program parser will produce the state[] values.
*/
static void
-_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
+_mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
GLfloat *value)
{
switch (state[0]) {
@@ -273,7 +273,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
case STATE_MVP_MATRIX:
case STATE_TEXTURE_MATRIX:
case STATE_PROGRAM_MATRIX:
- case STATE_COLOR_MATRIX:
{
/* state[0] = modelview, projection, texture, etc. */
/* state[1] = which texture matrix or program matrix */
@@ -309,9 +308,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
ASSERT(index < Elements(ctx->ProgramMatrixStack));
matrix = ctx->ProgramMatrixStack[index].Top;
}
- else if (mat == STATE_COLOR_MATRIX) {
- matrix = ctx->ColorMatrixStack.Top;
- }
else {
_mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
return;
@@ -555,14 +551,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[3] = ctx->Pixel.AlphaBias;
return;
- case STATE_PCM_SCALE:
- COPY_4V(value, ctx->Pixel.PostColorMatrixScale);
- return;
-
- case STATE_PCM_BIAS:
- COPY_4V(value, ctx->Pixel.PostColorMatrixBias);
- return;
-
case STATE_SHADOW_AMBIENT:
{
const int unit = (int) state[2];
@@ -667,8 +655,6 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
return _NEW_TEXTURE_MATRIX;
case STATE_PROGRAM_MATRIX:
return _NEW_TRACK_MATRIX;
- case STATE_COLOR_MATRIX:
- return _NEW_COLOR_MATRIX;
case STATE_DEPTH_RANGE:
return _NEW_VIEWPORT;
@@ -706,8 +692,6 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
case STATE_PT_SCALE:
case STATE_PT_BIAS:
- case STATE_PCM_SCALE:
- case STATE_PCM_BIAS:
return _NEW_PIXEL;
case STATE_FB_SIZE:
@@ -792,9 +776,6 @@ append_token(char *dst, gl_state_index k)
case STATE_PROGRAM_MATRIX:
append(dst, "matrix.program");
break;
- case STATE_COLOR_MATRIX:
- append(dst, "matrix.color");
- break;
case STATE_MATRIX_INVERSE:
append(dst, ".inverse");
break;
@@ -913,12 +894,6 @@ append_token(char *dst, gl_state_index k)
case STATE_PT_BIAS:
append(dst, "PTbias");
break;
- case STATE_PCM_SCALE:
- append(dst, "PCMscale");
- break;
- case STATE_PCM_BIAS:
- append(dst, "PCMbias");
- break;
case STATE_SHADOW_AMBIENT:
append(dst, "CompareFailValue");
break;
@@ -1010,7 +985,6 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
case STATE_MVP_MATRIX:
case STATE_TEXTURE_MATRIX:
case STATE_PROGRAM_MATRIX:
- case STATE_COLOR_MATRIX:
{
/* state[0] = modelview, projection, texture, etc. */
/* state[1] = which texture matrix or program matrix */
@@ -1075,7 +1049,7 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
* This would be called at glBegin time when using a fragment program.
*/
void
-_mesa_load_state_parameters(GLcontext *ctx,
+_mesa_load_state_parameters(struct gl_context *ctx,
struct gl_program_parameter_list *paramList)
{
GLuint i;
@@ -1129,7 +1103,7 @@ load_transpose_matrix(GLfloat registers[][4], GLuint pos,
* glBegin/glEnd, not per-vertex.
*/
void
-_mesa_load_tracked_matrices(GLcontext *ctx)
+_mesa_load_tracked_matrices(struct gl_context *ctx)
{
GLuint i;
@@ -1147,9 +1121,6 @@ _mesa_load_tracked_matrices(GLcontext *ctx)
Elements(ctx->TextureMatrixStack) - 1);
mat = ctx->TextureMatrixStack[unit].Top;
}
- else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) {
- mat = ctx->ColorMatrixStack.Top;
- }
else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
/* XXX verify the combined matrix is up to date */
mat = &ctx->_ModelProjectMatrix;
diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h
index 1753471ffb..6e5be53630 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -67,7 +67,6 @@ typedef enum gl_state_index_ {
STATE_MVP_MATRIX,
STATE_TEXTURE_MATRIX,
STATE_PROGRAM_MATRIX,
- STATE_COLOR_MATRIX,
STATE_MATRIX_INVERSE,
STATE_MATRIX_TRANSPOSE,
STATE_MATRIX_INVTRANS,
@@ -116,8 +115,6 @@ typedef enum gl_state_index_ {
STATE_LIGHT_HALF_VECTOR, /* object vs eye space */
STATE_PT_SCALE, /**< Pixel transfer RGBA scale */
STATE_PT_BIAS, /**< Pixel transfer RGBA bias */
- STATE_PCM_SCALE, /**< Post color matrix RGBA scale */
- STATE_PCM_BIAS, /**< Post color matrix RGBA bias */
STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */
STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
@@ -128,7 +125,7 @@ typedef enum gl_state_index_ {
extern void
-_mesa_load_state_parameters(GLcontext *ctx,
+_mesa_load_state_parameters(struct gl_context *ctx,
struct gl_program_parameter_list *paramList);
@@ -141,7 +138,7 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]);
extern void
-_mesa_load_tracked_matrices(GLcontext *ctx);
+_mesa_load_tracked_matrices(struct gl_context *ctx);
#endif /* PROG_STATEVARS_H */
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index 06b9539bda..cdcf4ec265 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -49,7 +49,7 @@ struct gl_program _mesa_DummyProgram;
* Init context's vertex/fragment program state
*/
void
-_mesa_init_program(GLcontext *ctx)
+_mesa_init_program(struct gl_context *ctx)
{
GLuint i;
@@ -128,7 +128,7 @@ _mesa_init_program(GLcontext *ctx)
* Free a context's vertex/fragment program state
*/
void
-_mesa_free_program_data(GLcontext *ctx)
+_mesa_free_program_data(struct gl_context *ctx)
{
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
@@ -161,7 +161,7 @@ _mesa_free_program_data(GLcontext *ctx)
* shared state.
*/
void
-_mesa_update_default_objects_program(GLcontext *ctx)
+_mesa_update_default_objects_program(struct gl_context *ctx)
{
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
@@ -203,7 +203,7 @@ _mesa_update_default_objects_program(GLcontext *ctx)
* This is generally called from within the parsers.
*/
void
-_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string)
+_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
{
ctx->Program.ErrorPos = pos;
free((void *) ctx->Program.ErrorString);
@@ -260,7 +260,7 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
* Initialize a new vertex/fragment program object.
*/
static struct gl_program *
-_mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog,
+_mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog,
GLenum target, GLuint id)
{
(void) ctx;
@@ -286,7 +286,7 @@ _mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog,
* Initialize a new fragment program object.
*/
struct gl_program *
-_mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog,
+_mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program *prog,
GLenum target, GLuint id)
{
if (prog)
@@ -300,7 +300,7 @@ _mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog,
* Initialize a new vertex program object.
*/
struct gl_program *
-_mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog,
+_mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *prog,
GLenum target, GLuint id)
{
if (prog)
@@ -314,7 +314,7 @@ _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog,
* Initialize a new geometry program object.
*/
struct gl_program *
-_mesa_init_geometry_program( GLcontext *ctx, struct gl_geometry_program *prog,
+_mesa_init_geometry_program( struct gl_context *ctx, struct gl_geometry_program *prog,
GLenum target, GLuint id)
{
if (prog)
@@ -337,7 +337,7 @@ _mesa_init_geometry_program( GLcontext *ctx, struct gl_geometry_program *prog,
* \return pointer to new program object
*/
struct gl_program *
-_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
+_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id)
{
struct gl_program *prog;
switch (target) {
@@ -372,7 +372,7 @@ _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
* by a device driver function.
*/
void
-_mesa_delete_program(GLcontext *ctx, struct gl_program *prog)
+_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
{
(void) ctx;
ASSERT(prog);
@@ -406,7 +406,7 @@ _mesa_delete_program(GLcontext *ctx, struct gl_program *prog)
* casts elsewhere.
*/
struct gl_program *
-_mesa_lookup_program(GLcontext *ctx, GLuint id)
+_mesa_lookup_program(struct gl_context *ctx, GLuint id)
{
if (id)
return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
@@ -419,7 +419,7 @@ _mesa_lookup_program(GLcontext *ctx, GLuint id)
* Reference counting for vertex/fragment programs
*/
void
-_mesa_reference_program(GLcontext *ctx,
+_mesa_reference_program(struct gl_context *ctx,
struct gl_program **ptr,
struct gl_program *prog)
{
@@ -486,7 +486,7 @@ _mesa_reference_program(GLcontext *ctx,
* made by a device driver.
*/
struct gl_program *
-_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog)
+_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
{
struct gl_program *clone;
@@ -729,7 +729,7 @@ adjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
* the first program go to the inputs of the second program.
*/
struct gl_program *
-_mesa_combine_programs(GLcontext *ctx,
+_mesa_combine_programs(struct gl_context *ctx,
const struct gl_program *progA,
const struct gl_program *progB)
{
@@ -923,7 +923,7 @@ _mesa_find_free_register(const GLboolean used[],
* behaviour.
*/
void
-_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog)
+_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
{
static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
GLuint i;
diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h
index 03b1066f32..70cc2c3aae 100644
--- a/src/mesa/program/program.h
+++ b/src/mesa/program/program.h
@@ -48,16 +48,16 @@ extern struct gl_program _mesa_DummyProgram;
extern void
-_mesa_init_program(GLcontext *ctx);
+_mesa_init_program(struct gl_context *ctx);
extern void
-_mesa_free_program_data(GLcontext *ctx);
+_mesa_free_program_data(struct gl_context *ctx);
extern void
-_mesa_update_default_objects_program(GLcontext *ctx);
+_mesa_update_default_objects_program(struct gl_context *ctx);
extern void
-_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
+_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string);
extern const GLubyte *
_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
@@ -65,36 +65,36 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
extern struct gl_program *
-_mesa_init_vertex_program(GLcontext *ctx,
+_mesa_init_vertex_program(struct gl_context *ctx,
struct gl_vertex_program *prog,
GLenum target, GLuint id);
extern struct gl_program *
-_mesa_init_fragment_program(GLcontext *ctx,
+_mesa_init_fragment_program(struct gl_context *ctx,
struct gl_fragment_program *prog,
GLenum target, GLuint id);
extern struct gl_program *
-_mesa_init_geometry_program(GLcontext *ctx,
+_mesa_init_geometry_program(struct gl_context *ctx,
struct gl_geometry_program *prog,
GLenum target, GLuint id);
extern struct gl_program *
-_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id);
+_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id);
extern void
-_mesa_delete_program(GLcontext *ctx, struct gl_program *prog);
+_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog);
extern struct gl_program *
-_mesa_lookup_program(GLcontext *ctx, GLuint id);
+_mesa_lookup_program(struct gl_context *ctx, GLuint id);
extern void
-_mesa_reference_program(GLcontext *ctx,
+_mesa_reference_program(struct gl_context *ctx,
struct gl_program **ptr,
struct gl_program *prog);
static INLINE void
-_mesa_reference_vertprog(GLcontext *ctx,
+_mesa_reference_vertprog(struct gl_context *ctx,
struct gl_vertex_program **ptr,
struct gl_vertex_program *prog)
{
@@ -103,7 +103,7 @@ _mesa_reference_vertprog(GLcontext *ctx,
}
static INLINE void
-_mesa_reference_fragprog(GLcontext *ctx,
+_mesa_reference_fragprog(struct gl_context *ctx,
struct gl_fragment_program **ptr,
struct gl_fragment_program *prog)
{
@@ -112,7 +112,7 @@ _mesa_reference_fragprog(GLcontext *ctx,
}
static INLINE void
-_mesa_reference_geomprog(GLcontext *ctx,
+_mesa_reference_geomprog(struct gl_context *ctx,
struct gl_geometry_program **ptr,
struct gl_geometry_program *prog)
{
@@ -121,24 +121,24 @@ _mesa_reference_geomprog(GLcontext *ctx,
}
extern struct gl_program *
-_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog);
+_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog);
static INLINE struct gl_vertex_program *
-_mesa_clone_vertex_program(GLcontext *ctx,
+_mesa_clone_vertex_program(struct gl_context *ctx,
const struct gl_vertex_program *prog)
{
return (struct gl_vertex_program *) _mesa_clone_program(ctx, &prog->Base);
}
static INLINE struct gl_geometry_program *
-_mesa_clone_geometry_program(GLcontext *ctx,
+_mesa_clone_geometry_program(struct gl_context *ctx,
const struct gl_geometry_program *prog)
{
return (struct gl_geometry_program *) _mesa_clone_program(ctx, &prog->Base);
}
static INLINE struct gl_fragment_program *
-_mesa_clone_fragment_program(GLcontext *ctx,
+_mesa_clone_fragment_program(struct gl_context *ctx,
const struct gl_fragment_program *prog)
{
return (struct gl_fragment_program *) _mesa_clone_program(ctx, &prog->Base);
@@ -152,7 +152,7 @@ extern GLboolean
_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count);
extern struct gl_program *
-_mesa_combine_programs(GLcontext *ctx,
+_mesa_combine_programs(struct gl_context *ctx,
const struct gl_program *progA,
const struct gl_program *progB);
@@ -166,7 +166,7 @@ _mesa_find_free_register(const GLboolean used[],
GLuint maxRegs, GLuint firstReg);
extern void
-_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog);
+_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog);
/* keep these in the same order as TGSI_PROCESSOR_* */
diff --git a/src/mesa/program/program_parse.tab.c b/src/mesa/program/program_parse.tab.c
index 08ead30def..baef311d0c 100644
--- a/src/mesa/program/program_parse.tab.c
+++ b/src/mesa/program/program_parse.tab.c
@@ -5604,7 +5604,7 @@ yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
GLboolean
-_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
+_mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *str,
GLsizei len, struct asm_parser_state *state)
{
struct asm_instruction *inst;
diff --git a/src/mesa/program/program_parse.y b/src/mesa/program/program_parse.y
index cf621ae424..784ea28c17 100644
--- a/src/mesa/program/program_parse.y
+++ b/src/mesa/program/program_parse.y
@@ -2643,7 +2643,7 @@ yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
GLboolean
-_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
+_mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *str,
GLsizei len, struct asm_parser_state *state)
{
struct asm_instruction *inst;
diff --git a/src/mesa/program/program_parser.h b/src/mesa/program/program_parser.h
index be952d4b9c..d689eef795 100644
--- a/src/mesa/program/program_parser.h
+++ b/src/mesa/program/program_parser.h
@@ -24,10 +24,7 @@
#include "main/config.h"
-#ifndef MTYPES_H
-struct __GLcontextRec;
-typedef struct __GLcontextRec GLcontext;
-#endif
+struct gl_context;
enum asm_type {
at_none,
@@ -131,7 +128,7 @@ struct asm_instruction {
struct asm_parser_state {
- GLcontext *ctx;
+ struct gl_context *ctx;
struct gl_program *prog;
/**
@@ -237,7 +234,7 @@ typedef struct YYLTYPE {
#define YYLTYPE_IS_TRIVIAL 1
-extern GLboolean _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
+extern GLboolean _mesa_parse_arb_program(struct gl_context *ctx, GLenum target,
const GLubyte *str, GLsizei len, struct asm_parser_state *state);
diff --git a/src/mesa/program/programopt.c b/src/mesa/program/programopt.c
index fb2ebe6338..f92881f833 100644
--- a/src/mesa/program/programopt.c
+++ b/src/mesa/program/programopt.c
@@ -46,7 +46,7 @@
* May be used to implement the position_invariant option.
*/
static void
-_mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+_mesa_insert_mvp_dp4_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
{
struct prog_instruction *newInst;
const GLuint origLen = vprog->Base.NumInstructions;
@@ -114,7 +114,7 @@ _mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog)
static void
-_mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+_mesa_insert_mvp_mad_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
{
struct prog_instruction *newInst;
const GLuint origLen = vprog->Base.NumInstructions;
@@ -216,7 +216,7 @@ _mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog)
void
-_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+_mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
{
if (ctx->mvp_with_dp4)
_mesa_insert_mvp_dp4_code( ctx, vprog );
@@ -238,7 +238,7 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
* to vertex programs too.
*/
void
-_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
+_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
{
static const gl_state_index fogPStateOpt[STATE_LENGTH]
= { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
@@ -585,7 +585,7 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type)
* This is for debug/test purposes.
*/
void
-_mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog)
+_mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog)
{
struct prog_instruction *inst;
GLuint inputAttr;
@@ -626,7 +626,7 @@ _mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog)
* transforms vertex position and emits color.
*/
void
-_mesa_nop_vertex_program(GLcontext *ctx, struct gl_vertex_program *prog)
+_mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog)
{
struct prog_instruction *inst;
GLuint inputAttr;
diff --git a/src/mesa/program/programopt.h b/src/mesa/program/programopt.h
index 4af6357f97..ef6f1bd079 100644
--- a/src/mesa/program/programopt.h
+++ b/src/mesa/program/programopt.h
@@ -29,10 +29,10 @@
#include "main/mtypes.h"
extern void
-_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog);
+_mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog);
extern void
-_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog);
+_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog);
extern void
_mesa_count_texture_indirections(struct gl_program *prog);
@@ -44,10 +44,10 @@ extern void
_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type);
extern void
-_mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog);
+_mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog);
extern void
-_mesa_nop_vertex_program(GLcontext *ctx, struct gl_vertex_program *prog);
+_mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog);
#endif /* PROGRAMOPT_H */
diff --git a/src/mesa/program/register_allocate.c b/src/mesa/program/register_allocate.c
new file mode 100644
index 0000000000..03f04697bf
--- /dev/null
+++ b/src/mesa/program/register_allocate.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file register_allocate.c
+ *
+ * Graph-coloring register allocator.
+ */
+
+#include <talloc.h>
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "register_allocate.h"
+
+struct ra_reg {
+ char *name;
+ GLboolean *conflicts;
+};
+
+struct ra_regs {
+ struct ra_reg *regs;
+ unsigned int count;
+
+ struct ra_class **classes;
+ unsigned int class_count;
+};
+
+struct ra_class {
+ GLboolean *regs;
+
+ /**
+ * p_B in Runeson/Nyström paper.
+ *
+ * This is "how many regs are in the set."
+ */
+ unsigned int p;
+
+ /**
+ * q_B,C in Runeson/Nyström paper.
+ */
+ unsigned int *q;
+};
+
+struct ra_node {
+ GLboolean *adjacency;
+ unsigned int class;
+ unsigned int adjacency_count;
+ unsigned int reg;
+ GLboolean in_stack;
+};
+
+struct ra_graph {
+ struct ra_regs *regs;
+ /**
+ * the variables that need register allocation.
+ */
+ struct ra_node *nodes;
+ unsigned int count; /**< count of nodes. */
+
+ unsigned int *stack;
+ unsigned int stack_count;
+};
+
+struct ra_regs *
+ra_alloc_reg_set(unsigned int count)
+{
+ unsigned int i;
+ struct ra_regs *regs;
+
+ regs = talloc_zero(NULL, struct ra_regs);
+ regs->count = count;
+ regs->regs = talloc_zero_array(regs, struct ra_reg, count);
+
+ for (i = 0; i < count; i++) {
+ regs->regs[i].conflicts = talloc_zero_array(regs->regs, GLboolean, count);
+ regs->regs[i].conflicts[i] = GL_TRUE;
+ }
+
+ return regs;
+}
+
+void
+ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2)
+{
+ regs->regs[r1].conflicts[r2] = GL_TRUE;
+ regs->regs[r2].conflicts[r1] = GL_TRUE;
+}
+
+unsigned int
+ra_alloc_reg_class(struct ra_regs *regs)
+{
+ struct ra_class *class;
+
+ regs->classes = talloc_realloc(regs, regs->classes,
+ struct ra_class *,
+ regs->class_count + 1);
+
+ class = talloc_zero(regs, struct ra_class);
+ regs->classes[regs->class_count] = class;
+
+ class->regs = talloc_zero_array(class, GLboolean, regs->count);
+
+ return regs->class_count++;
+}
+
+void
+ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int r)
+{
+ struct ra_class *class = regs->classes[c];
+
+ class->regs[r] = GL_TRUE;
+ class->p++;
+}
+
+/**
+ * Must be called after all conflicts and register classes have been
+ * set up and before the register set is used for allocation.
+ */
+void
+ra_set_finalize(struct ra_regs *regs)
+{
+ unsigned int b, c;
+
+ for (b = 0; b < regs->class_count; b++) {
+ regs->classes[b]->q = talloc_array(regs, unsigned int, regs->class_count);
+ }
+
+ /* Compute, for each class B and C, how many regs of B an
+ * allocation to C could conflict with.
+ */
+ for (b = 0; b < regs->class_count; b++) {
+ for (c = 0; c < regs->class_count; c++) {
+ unsigned int rc;
+ int max_conflicts = 0;
+
+ for (rc = 0; rc < regs->count; rc++) {
+ unsigned int rb;
+ int conflicts = 0;
+
+ if (!regs->classes[c]->regs[rc])
+ continue;
+
+ for (rb = 0; rb < regs->count; rb++) {
+ if (regs->classes[b]->regs[rb] &&
+ regs->regs[rb].conflicts[rc])
+ conflicts++;
+ }
+ max_conflicts = MAX2(max_conflicts, conflicts);
+ }
+ regs->classes[b]->q[c] = max_conflicts;
+ }
+ }
+}
+
+struct ra_graph *
+ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count)
+{
+ struct ra_graph *g;
+ unsigned int i;
+
+ g = talloc_zero(regs, struct ra_graph);
+ g->regs = regs;
+ g->nodes = talloc_zero_array(g, struct ra_node, count);
+ g->count = count;
+
+ g->stack = talloc_zero_array(g, unsigned int, count);
+
+ for (i = 0; i < count; i++) {
+ g->nodes[i].adjacency = talloc_zero_array(g, GLboolean, count);
+ g->nodes[i].adjacency[i] = GL_TRUE;
+ g->nodes[i].reg = ~0;
+ }
+
+ return g;
+}
+
+void
+ra_set_node_class(struct ra_graph *g,
+ unsigned int n, unsigned int class)
+{
+ g->nodes[n].class = class;
+}
+
+void
+ra_add_node_interference(struct ra_graph *g,
+ unsigned int n1, unsigned int n2)
+{
+ if (g->nodes[n1].adjacency[n2])
+ return;
+
+ g->nodes[n1].adjacency[n2] = GL_TRUE;
+ g->nodes[n2].adjacency_count++;
+ g->nodes[n2].adjacency[n1] = GL_TRUE;
+ g->nodes[n2].adjacency_count++;
+}
+
+static GLboolean pq_test(struct ra_graph *g, unsigned int n)
+{
+ unsigned int j;
+ unsigned int q = 0;
+ int n_class = g->nodes[n].class;
+
+ for (j = 0; j < g->count; j++) {
+ if (j == n || g->nodes[j].in_stack)
+ continue;
+
+ if (g->nodes[n].adjacency[j]) {
+ unsigned int j_class = g->nodes[j].class;
+ q += g->regs->classes[n_class]->q[j_class];
+ }
+ }
+
+ return q < g->regs->classes[n_class]->p;
+}
+
+/**
+ * Simplifies the interference graph by pushing all
+ * trivially-colorable nodes into a stack of nodes to be colored,
+ * removing them from the graph, and rinsing and repeating.
+ *
+ * Returns GL_TRUE if all nodes were removed from the graph. GL_FALSE
+ * means that either spilling will be required, or optimistic coloring
+ * should be applied.
+ */
+GLboolean
+ra_simplify(struct ra_graph *g)
+{
+ GLboolean progress = GL_TRUE;
+ int i;
+
+ while (progress) {
+ progress = GL_FALSE;
+
+ for (i = g->count - 1; i >= 0; i--) {
+ if (g->nodes[i].in_stack)
+ continue;
+
+ if (pq_test(g, i)) {
+ g->stack[g->stack_count] = i;
+ g->stack_count++;
+ g->nodes[i].in_stack = GL_TRUE;
+ progress = GL_TRUE;
+ }
+ }
+ }
+
+ for (i = 0; i < g->count; i++) {
+ if (!g->nodes[i].in_stack)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+/**
+ * Pops nodes from the stack back into the graph, coloring them with
+ * registers as they go.
+ *
+ * If all nodes were trivially colorable, then this must succeed. If
+ * not (optimistic coloring), then it may return GL_FALSE;
+ */
+GLboolean
+ra_select(struct ra_graph *g)
+{
+ int i;
+
+ while (g->stack_count != 0) {
+ unsigned int r;
+ int n = g->stack[g->stack_count - 1];
+ struct ra_class *c = g->regs->classes[g->nodes[n].class];
+
+ /* Find the lowest-numbered reg which is not used by a member
+ * of the graph adjacent to us.
+ */
+ for (r = 0; r < g->regs->count; r++) {
+ if (!c->regs[r])
+ continue;
+
+ /* Check if any of our neighbors conflict with this register choice. */
+ for (i = 0; i < g->count; i++) {
+ if (g->nodes[n].adjacency[i] &&
+ !g->nodes[i].in_stack &&
+ g->regs->regs[r].conflicts[g->nodes[i].reg]) {
+ break;
+ }
+ }
+ if (i == g->count)
+ break;
+ }
+ if (r == g->regs->count)
+ return GL_FALSE;
+
+ g->nodes[n].reg = r;
+ g->nodes[n].in_stack = GL_FALSE;
+ g->stack_count--;
+ }
+
+ return GL_TRUE;
+}
+
+/**
+ * Optimistic register coloring: Just push the remaining nodes
+ * on the stack. They'll be colored first in ra_select(), and
+ * if they succeed then the locally-colorable nodes are still
+ * locally-colorable and the rest of the register allocation
+ * will succeed.
+ */
+void
+ra_optimistic_color(struct ra_graph *g)
+{
+ unsigned int i;
+
+ for (i = 0; i < g->count; i++) {
+ if (g->nodes[i].in_stack)
+ continue;
+
+ g->stack[g->stack_count] = i;
+ g->stack_count++;
+ g->nodes[i].in_stack = GL_TRUE;
+ }
+}
+
+GLboolean
+ra_allocate_no_spills(struct ra_graph *g)
+{
+ if (!ra_simplify(g)) {
+ ra_optimistic_color(g);
+ }
+ return ra_select(g);
+}
+
+unsigned int
+ra_get_node_reg(struct ra_graph *g, unsigned int n)
+{
+ return g->nodes[n].reg;
+}
diff --git a/src/mesa/program/register_allocate.h b/src/mesa/program/register_allocate.h
new file mode 100644
index 0000000000..42647b50b8
--- /dev/null
+++ b/src/mesa/program/register_allocate.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+struct ra_class;
+struct ra_regs;
+
+/* @{
+ * Register set setup.
+ *
+ * This should be done once at backend initializaion, as
+ * ra_set_finalize is O(r^2*c^2). The registers may be virtual
+ * registers, such as aligned register pairs that conflict with the
+ * two real registers from which they are composed.
+ */
+struct ra_regs *ra_alloc_reg_set(unsigned int count);
+unsigned int ra_alloc_reg_class(struct ra_regs *regs);
+void ra_add_reg_conflict(struct ra_regs *regs,
+ unsigned int r1, unsigned int r2);
+void ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int reg);
+void ra_set_finalize(struct ra_regs *regs);
+/** @} */
+
+/** @{ Interference graph setup.
+ *
+ * Each interference graph node is a virtual variable in the IL. It
+ * is up to the user to ra_set_node_class() for the virtual variable,
+ * and compute live ranges and ra_node_interfere() between conflicting
+ * live ranges.
+ */
+struct ra_graph *ra_alloc_interference_graph(struct ra_regs *regs,
+ unsigned int count);
+void ra_set_node_class(struct ra_graph *g, unsigned int n, unsigned int c);
+void ra_add_node_interference(struct ra_graph *g,
+ unsigned int n1, unsigned int n2);
+/** @} */
+
+/** @{ Graph-coloring register allocation */
+GLboolean ra_simplify(struct ra_graph *g);
+void ra_optimistic_color(struct ra_graph *g);
+GLboolean ra_select(struct ra_graph *g);
+GLboolean ra_allocate_no_spills(struct ra_graph *g);
+
+unsigned int ra_get_node_reg(struct ra_graph *g, unsigned int n);
+/** @} */
+
diff --git a/src/mesa/program/sampler.cpp b/src/mesa/program/sampler.cpp
new file mode 100644
index 0000000000..0e58aef9c9
--- /dev/null
+++ b/src/mesa/program/sampler.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+extern "C" {
+#include "main/compiler.h"
+#include "main/mtypes.h"
+#include "program/prog_parameter.h"
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+}
+
+static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
+
+static void fail_link(struct gl_shader_program *prog, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args);
+ va_end(args);
+
+ prog->LinkStatus = GL_FALSE;
+}
+
+class get_sampler_name : public ir_hierarchical_visitor
+{
+public:
+ get_sampler_name(ir_dereference *last,
+ struct gl_shader_program *shader_program)
+ {
+ this->mem_ctx = talloc_new(NULL);
+ this->shader_program = shader_program;
+ this->name = NULL;
+ this->offset = 0;
+ this->last = last;
+ }
+
+ ~get_sampler_name()
+ {
+ talloc_free(this->mem_ctx);
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ this->name = ir->var->name;
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
+ {
+ this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
+ return visit_continue;
+ }
+
+ virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
+ {
+ ir_constant *index = ir->array_index->as_constant();
+ int i;
+
+ if (index) {
+ i = index->value.i[0];
+ } else {
+ /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
+ * while GLSL 1.30 requires that the array indices be
+ * constant integer expressions. We don't expect any driver
+ * to actually work with a really variable array index, so
+ * all that would work would be an unrolled loop counter that ends
+ * up being constant above.
+ */
+ shader_program->InfoLog =
+ talloc_asprintf_append(shader_program->InfoLog,
+ "warning: Variable sampler array index "
+ "unsupported.\nThis feature of the language "
+ "was removed in GLSL 1.20 and is unlikely "
+ "to be supported for 1.10 in Mesa.\n");
+ i = 0;
+ }
+ if (ir != last) {
+ this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i);
+ } else {
+ offset = i;
+ }
+ return visit_continue;
+ }
+
+ struct gl_shader_program *shader_program;
+ const char *name;
+ void *mem_ctx;
+ int offset;
+ ir_dereference *last;
+};
+
+extern "C" {
+int
+_mesa_get_sampler_uniform_value(class ir_dereference *sampler,
+ struct gl_shader_program *shader_program,
+ const struct gl_program *prog)
+{
+ get_sampler_name getname(sampler, shader_program);
+
+ sampler->accept(&getname);
+
+ GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
+ getname.name);
+
+ if (index < 0) {
+ fail_link(shader_program,
+ "failed to find sampler named %s.\n", getname.name);
+ return 0;
+ }
+
+ index += getname.offset;
+
+ return prog->Parameters->ParameterValues[index][0];
+}
+}
diff --git a/src/mesa/program/sampler.h b/src/mesa/program/sampler.h
new file mode 100644
index 0000000000..22467e9902
--- /dev/null
+++ b/src/mesa/program/sampler.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+int
+_mesa_get_sampler_uniform_value(class ir_dereference *sampler,
+ struct gl_shader_program *shader_program,
+ const struct gl_program *prog);