/*
* Mesa 3-D graphics library
- * Version: 6.3.1
+ * Version: 7.1
*
- * Copyright (C) 2005 Tungsten Graphics All Rights Reserved.
+ * Copyright (C) 2007 Tungsten Graphics 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"),
#include "glheader.h"
#include "macros.h"
#include "enums.h"
-#include "t_context.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "t_context.h" /* NOTE: very light dependency on this */
#include "t_vp_build.h"
-#include "shader/program.h"
-#include "shader/nvvertprog.h"
-#include "shader/arbvertparse.h"
struct state_key {
unsigned light_global_enabled:1;
unsigned fog_source_is_depth:1;
unsigned tnl_do_vertex_fog:1;
unsigned separate_specular:1;
- unsigned fog_enabled:1;
unsigned fog_mode:2;
unsigned point_attenuated:1;
unsigned texture_enabled_global:1;
+ unsigned fragprog_inputs_read:12;
struct {
unsigned light_enabled:1;
-#define FOG_LINEAR 0
-#define FOG_EXP 1
-#define FOG_EXP2 2
-#define FOG_UNKNOWN 3
+#define FOG_NONE 0
+#define FOG_LINEAR 1
+#define FOG_EXP 2
+#define FOG_EXP2 3
static GLuint translate_fog_mode( GLenum mode )
{
case GL_LINEAR: return FOG_LINEAR;
case GL_EXP: return FOG_EXP;
case GL_EXP2: return FOG_EXP2;
- default: return FOG_UNKNOWN;
+ default: return FOG_NONE;
}
}
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
struct state_key *key = CALLOC_STRUCT(state_key);
GLuint i;
+ /* This now relies on texenvprogram.c being active:
+ */
+ assert(fp);
+
+ key->fragprog_inputs_read = fp->Base.InputsRead;
+
key->separate_specular = (ctx->Light.Model.ColorControl ==
GL_SEPARATE_SPECULAR_COLOR);
key->light_color_material_mask = ctx->Light.ColorMaterialBitmask;
}
- for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; i < _TNL_ATTRIB_INDEX ; i++)
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++)
if (VB->AttribPtr[i]->stride)
key->light_material_mask |= 1<<(i-_TNL_ATTRIB_MAT_FRONT_AMBIENT);
if (ctx->Transform.RescaleNormals)
key->rescale_normals = 1;
- if (ctx->Fog.Enabled)
- key->fog_enabled = 1;
-
- if (key->fog_enabled) {
- if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
- key->fog_source_is_depth = 1;
-
- if (tnl->_DoVertexFog)
- key->tnl_do_vertex_fog = 1;
-
- key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
- }
+ key->fog_mode = translate_fog_mode(fp->FogOption);
+
+ if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
+ key->fog_source_is_depth = 1;
+
+ if (tnl->_DoVertexFog)
+ key->tnl_do_vertex_fog = 1;
if (ctx->Point._Attenuated)
key->point_attenuated = 1;
*/
#define PREFER_DP4 0
-#define MAX_INSN 200
+#define MAX_INSN 256
/* Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
struct tnl_program {
const struct state_key *state;
- struct vertex_program *program;
+ struct gl_vertex_program *program;
GLuint temp_in_use;
GLuint temp_reserved;
};
-const static struct ureg undef = {
- ~0,
+static const struct ureg undef = {
+ PROGRAM_UNDEFINED,
~0,
0,
0,
_mesa_exit(1);
}
+ if ((GLuint) bit > p->program->Base.NumTemporaries)
+ p->program->Base.NumTemporaries = bit;
+
p->temp_in_use |= 1<<(bit-1);
return make_ureg(PROGRAM_TEMPORARY, bit-1);
}
static struct ureg register_input( struct tnl_program *p, GLuint input )
{
- p->program->InputsRead |= (1<<input);
+ p->program->Base.InputsRead |= (1<<input);
return make_ureg(PROGRAM_INPUT, input);
}
static struct ureg register_output( struct tnl_program *p, GLuint output )
{
- p->program->OutputsWritten |= (1<<output);
+ p->program->Base.OutputsWritten |= (1<<output);
return make_ureg(PROGRAM_OUTPUT, output);
}
{
GLfloat values[4];
GLint idx;
+ GLuint swizzle;
values[0] = s0;
values[1] = s1;
values[2] = s2;
values[3] = s3;
- idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
+ idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
+ &swizzle );
+ ASSERT(swizzle == SWIZZLE_NOOP);
return make_ureg(PROGRAM_STATE_VAR, idx);
}
static GLboolean is_undef( struct ureg reg )
{
- return reg.file == 0xf;
+ return reg.file == PROGRAM_UNDEFINED;
}
static struct ureg get_identity_param( struct tnl_program *p )
return p->identity;
}
-static struct ureg register_param6( struct tnl_program *p,
+static struct ureg register_param5(struct tnl_program *p,
GLint s0,
GLint s1,
GLint s2,
GLint s3,
- GLint s4,
- GLint s5)
+ GLint s4)
{
- GLint tokens[6];
+ gl_state_index tokens[STATE_LENGTH];
GLint idx;
tokens[0] = s0;
tokens[1] = s1;
tokens[2] = s2;
tokens[3] = s3;
tokens[4] = s4;
- tokens[5] = s5;
- idx = _mesa_add_state_reference( p->program->Parameters, tokens );
+ idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
return make_ureg(PROGRAM_STATE_VAR, idx);
}
-#define register_param1(p,s0) register_param6(p,s0,0,0,0,0,0)
-#define register_param2(p,s0,s1) register_param6(p,s0,s1,0,0,0,0)
-#define register_param3(p,s0,s1,s2) register_param6(p,s0,s1,s2,0,0,0)
-#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
+#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
+#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
+#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
-static void register_matrix_param6( struct tnl_program *p,
- GLint s0,
- GLint s1,
- GLint s2,
- GLint s3,
- GLint s4,
- GLint s5,
+static void register_matrix_param5( struct tnl_program *p,
+ GLint s0, /* modelview, projection, etc */
+ GLint s1, /* texture matrix number */
+ GLint s2, /* first row */
+ GLint s3, /* last row */
+ GLint s4, /* inverse, transpose, etc */
struct ureg *matrix )
{
- GLuint i;
+ GLint i;
/* This is a bit sad as the support is there to pull the whole
* matrix out in one go:
*/
- for (i = 0; i <= s4 - s3; i++)
- matrix[i] = register_param6( p, s0, s1, s2, i, i, s5 );
+ for (i = 0; i <= s3 - s2; i++)
+ matrix[i] = register_param5( p, s0, s1, i, i, s4 );
}
-static void emit_arg( struct vp_src_register *src,
+/**
+ * Convert a ureg source register to a prog_src_register.
+ */
+static void emit_arg( struct prog_src_register *src,
struct ureg reg )
{
+ assert(reg.file != PROGRAM_OUTPUT);
src->File = reg.file;
src->Index = reg.idx;
src->Swizzle = reg.swz;
- src->Negate = reg.negate;
+ src->NegateBase = reg.negate ? NEGATE_XYZW : 0;
+ src->Abs = 0;
+ src->NegateAbs = 0;
src->RelAddr = 0;
- src->pad = 0;
}
-static void emit_dst( struct vp_dst_register *dst,
+/**
+ * Convert a ureg dest register to a prog_dst_register.
+ */
+static void emit_dst( struct prog_dst_register *dst,
struct ureg reg, GLuint mask )
{
+ /* Check for legal output register type. UNDEFINED will occur in
+ * instruction that don't produce a result (like END).
+ */
+ assert(reg.file == PROGRAM_TEMPORARY ||
+ reg.file == PROGRAM_OUTPUT ||
+ reg.file == PROGRAM_UNDEFINED);
dst->File = reg.file;
dst->Index = reg.idx;
/* allow zero as a shorthand for xyzw */
dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
+ dst->CondMask = COND_TR;
+ dst->CondSwizzle = 0;
+ dst->CondSrc = 0;
dst->pad = 0;
}
-static void debug_insn( struct vp_instruction *inst, const char *fn,
+static void debug_insn( struct prog_instruction *inst, const char *fn,
GLuint line )
{
if (DISASSEM) {
}
_mesa_printf("%d:\t", line);
- _mesa_debug_vp_inst(1, inst);
+ _mesa_print_instruction(inst);
}
}
GLuint line)
{
GLuint nr = p->program->Base.NumInstructions++;
- struct vp_instruction *inst = &p->program->Instructions[nr];
+ struct prog_instruction *inst = &p->program->Base.Instructions[nr];
if (p->program->Base.NumInstructions > MAX_INSN) {
_mesa_problem(0, "Out of instructions in emit_op3fn\n");
return;
}
- inst->Opcode = op;
+ inst->Opcode = (enum prog_opcode) op;
inst->StringPos = 0;
inst->Data = 0;
return reg;
else {
struct ureg temp = get_temp(p);
- emit_op1(p, VP_OPCODE_MOV, temp, 0, reg);
+ emit_op1(p, OPCODE_MOV, temp, 0, reg);
return temp;
}
}
const struct ureg *mat,
struct ureg src)
{
- emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
- emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
- emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
- emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
}
/* This version is much easier to implement if writemasks are not
else
tmp = dest;
- emit_op2(p, VP_OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
- emit_op3(p, VP_OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
- emit_op3(p, VP_OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
- emit_op3(p, VP_OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
+ emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
+ emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
+ emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
+ emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
if (dest.file != PROGRAM_TEMPORARY)
release_temp(p, tmp);
const struct ureg *mat,
struct ureg src)
{
- emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
- emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
- emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
+ emit_op2(p, OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
+ emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
+ emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
}
struct ureg src )
{
struct ureg tmp = get_temp(p);
- emit_op2(p, VP_OPCODE_DP3, tmp, 0, src, src);
- emit_op1(p, VP_OPCODE_RSQ, tmp, 0, tmp);
- emit_op2(p, VP_OPCODE_MUL, dest, 0, src, tmp);
+ emit_op2(p, OPCODE_DP3, tmp, 0, src, src);
+ emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
+ emit_op2(p, OPCODE_MUL, dest, 0, src, tmp);
release_temp(p, tmp);
}
GLuint output )
{
struct ureg out = register_output(p, output);
- emit_op1(p, VP_OPCODE_MOV, out, 0, register_input(p, input));
+ emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input));
}
static struct ureg get_eye_position( struct tnl_program *p )
p->eye_position = reserve_temp(p);
if (PREFER_DP4) {
- register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3,
- STATE_MATRIX, modelview );
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
+ 0, modelview );
emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
}
else {
- register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3,
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
STATE_MATRIX_TRANSPOSE, modelview );
emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
struct ureg mvinv[3];
- register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 2,
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
STATE_MATRIX_INVTRANS, mvinv );
p->eye_normal = reserve_temp(p);
struct ureg rescale = register_param2(p, STATE_INTERNAL,
STATE_NORMAL_SCALE);
- emit_op2( p, VP_OPCODE_MUL, p->eye_normal, 0, normal,
+ emit_op2( p, OPCODE_MUL, p->eye_normal, 0, p->eye_normal,
swizzle1(rescale, X));
}
}
struct ureg mvp[4];
if (PREFER_DP4) {
- register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3,
- STATE_MATRIX, mvp );
+ register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
+ 0, mvp );
emit_matrix_transform_vec4( p, hpos, mvp, pos );
}
else {
- register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3,
+ register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
STATE_MATRIX_TRANSPOSE, mvp );
emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
}
side);
}
+/* Get a bitmask of which material values vary on a per-vertex basis.
+ */
static void set_material_flags( struct tnl_program *p )
{
p->color_materials = 0;
struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
struct ureg tmp = make_temp(p, material_diffuse);
- emit_op3(p, VP_OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient,
+ emit_op3(p, OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient,
material_ambient, material_emission);
return tmp;
}
register_param3(p, STATE_LIGHT, light, property);
struct ureg material_value = get_material(p, side, property);
struct ureg tmp = get_temp(p);
- emit_op2(p, VP_OPCODE_MUL, tmp, 0, light_value, material_value);
+ emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value);
return tmp;
}
else
/* Calculate spot attenuation:
*/
if (!p->state->unit[i].light_spotcutoff_is_180) {
- struct ureg spot_dir = register_param3(p, STATE_LIGHT, i,
- STATE_SPOT_DIRECTION);
+ struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
+ STATE_SPOT_DIR_NORMALIZED, i);
struct ureg spot = get_temp(p);
struct ureg slt = get_temp(p);
-
- emit_normalize_vec3( p, spot, spot_dir ); /* XXX: precompute! */
- emit_op2(p, VP_OPCODE_DP3, spot, 0, negate(VPpli), spot);
- emit_op2(p, VP_OPCODE_SLT, slt, 0, swizzle1(spot_dir,W), spot);
- emit_op2(p, VP_OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
- emit_op2(p, VP_OPCODE_MUL, att, 0, slt, spot);
+
+ emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm);
+ emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
+ emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
+ emit_op2(p, OPCODE_MUL, att, 0, slt, spot);
release_temp(p, spot);
release_temp(p, slt);
if (p->state->unit[i].light_attenuated) {
/* 1/d,d,d,1/d */
- emit_op1(p, VP_OPCODE_RCP, dist, WRITEMASK_YZ, dist);
+ emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
/* 1,d,d*d,1/d */
- emit_op2(p, VP_OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
+ emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
/* 1/dist-atten */
- emit_op2(p, VP_OPCODE_DP3, dist, 0, attenuation, dist);
+ emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist);
if (!p->state->unit[i].light_spotcutoff_is_180) {
/* dist-atten */
- emit_op1(p, VP_OPCODE_RCP, dist, 0, dist);
+ emit_op1(p, OPCODE_RCP, dist, 0, dist);
/* spot-atten * dist-atten */
- emit_op2(p, VP_OPCODE_MUL, att, 0, dist, att);
+ emit_op2(p, OPCODE_MUL, att, 0, dist, att);
} else {
/* dist-atten */
- emit_op1(p, VP_OPCODE_RCP, att, 0, dist);
+ emit_op1(p, OPCODE_RCP, att, 0, dist);
}
}
/* Need to add some addtional parameters to allow lighting in object
- * space - STATE_SPOT_DIRECTION and STATE_HALF implicitly assume eye
+ * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
* space lighting.
*/
static void build_lighting( struct tnl_program *p )
{
struct ureg shininess = get_material(p, 0, STATE_SHININESS);
- emit_op1(p, VP_OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X));
+ emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X));
release_temp(p, shininess);
_col0 = make_temp(p, get_scenecolor(p, 0));
if (twoside) {
struct ureg shininess = get_material(p, 1, STATE_SHININESS);
- emit_op1(p, VP_OPCODE_MOV, dots, WRITEMASK_Z,
+ emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
negate(swizzle1(shininess,X)));
release_temp(p, shininess);
*/
{
struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
- emit_op1(p, VP_OPCODE_MOV, res0, 0, _col0);
+ emit_op1(p, OPCODE_MOV, res0, 0, _col0);
}
if (separate) {
struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
- emit_op1(p, VP_OPCODE_MOV, res1, 0, _col1);
+ emit_op1(p, OPCODE_MOV, res1, 0, _col1);
}
if (twoside) {
struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
- emit_op1(p, VP_OPCODE_MOV, res0, 0, _bfc0);
+ emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
}
if (twoside && separate) {
struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
- emit_op1(p, VP_OPCODE_MOV, res1, 0, _bfc1);
+ emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
}
if (nr_lights == 0) {
*/
VPpli = register_param3(p, STATE_LIGHT, i,
STATE_POSITION_NORMALIZED);
- half = register_param3(p, STATE_LIGHT, i, STATE_HALF);
+ if (p->state->light_local_viewer) {
+ struct ureg eye_hat = get_eye_position_normalized(p);
+ half = get_temp(p);
+ emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
+ emit_normalize_vec3(p, half, half);
+ } else {
+ half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
+ }
}
else {
struct ureg Ppli = register_param3(p, STATE_LIGHT, i,
STATE_POSITION);
struct ureg V = get_eye_position(p);
struct ureg dist = get_temp(p);
+ struct ureg tmpPpli = get_temp(p);
VPpli = get_temp(p);
half = get_temp(p);
- /* Calulate VPpli vector
+ /* In homogeneous object coordinates
+ */
+ emit_op1(p, OPCODE_RCP, dist, 0, swizzle1(Ppli, W));
+ emit_op2(p, OPCODE_MUL, tmpPpli, 0, Ppli, dist);
+
+ /* Calculate VPpli vector
*/
- emit_op2(p, VP_OPCODE_SUB, VPpli, 0, Ppli, V);
+ emit_op2(p, OPCODE_SUB, VPpli, 0, tmpPpli, V);
/* Normalize VPpli. The dist value also used in
* attenuation below.
*/
- emit_op2(p, VP_OPCODE_DP3, dist, 0, VPpli, VPpli);
- emit_op1(p, VP_OPCODE_RSQ, dist, 0, dist);
- emit_op2(p, VP_OPCODE_MUL, VPpli, 0, VPpli, dist);
+ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli);
+ emit_op1(p, OPCODE_RSQ, dist, 0, dist);
+ emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
/* Calculate attenuation:
*/
if (p->state->light_local_viewer) {
struct ureg eye_hat = get_eye_position_normalized(p);
- emit_op2(p, VP_OPCODE_SUB, half, 0, VPpli, eye_hat);
+ emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
}
else {
struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
- emit_op2(p, VP_OPCODE_ADD, half, 0, VPpli, z_dir);
+ emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
}
emit_normalize_vec3(p, half, half);
release_temp(p, dist);
+ release_temp(p, tmpPpli);
}
/* Calculate dot products:
*/
- emit_op2(p, VP_OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
- emit_op2(p, VP_OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
+ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
+ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
/* Front face lighting:
struct ureg res0, res1;
GLuint mask0, mask1;
- emit_op1(p, VP_OPCODE_LIT, lit, 0, dots);
+ emit_op1(p, OPCODE_LIT, lit, 0, dots);
if (!is_undef(att))
- emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att);
+ emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
if (count == nr_lights) {
res1 = _col1;
}
- emit_op3(p, VP_OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
- emit_op3(p, VP_OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0);
- emit_op3(p, VP_OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1);
+ emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
+ emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0);
+ emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1);
release_temp(p, ambient);
release_temp(p, diffuse);
struct ureg res0, res1;
GLuint mask0, mask1;
- emit_op1(p, VP_OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));
+ emit_op1(p, OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));
if (!is_undef(att))
- emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att);
+ emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
if (count == nr_lights) {
if (separate) {
mask1 = 0;
}
- emit_op3(p, VP_OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
- emit_op3(p, VP_OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
- emit_op3(p, VP_OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
+ emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
+ emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
+ emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
release_temp(p, ambient);
release_temp(p, diffuse);
{
struct ureg fog = register_output(p, VERT_RESULT_FOGC);
struct ureg input;
-
+
if (p->state->fog_source_is_depth) {
input = swizzle1(get_eye_position(p), Z);
}
input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
}
- if (p->state->tnl_do_vertex_fog) {
- struct ureg params = register_param1(p, STATE_FOG_PARAMS);
+ if (p->state->fog_mode && p->state->tnl_do_vertex_fog) {
+ struct ureg params = register_param2(p, STATE_INTERNAL,
+ STATE_FOG_PARAMS_OPTIMIZED);
struct ureg tmp = get_temp(p);
+ GLboolean useabs = (p->state->fog_mode != FOG_EXP2);
+
+ if (useabs) {
+ emit_op1(p, OPCODE_ABS, tmp, 0, input);
+ }
switch (p->state->fog_mode) {
case FOG_LINEAR: {
struct ureg id = get_identity_param(p);
- emit_op2(p, VP_OPCODE_SUB, tmp, 0, swizzle1(params,Z), input);
- emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, swizzle1(params,W));
- emit_op2(p, VP_OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
- emit_op2(p, VP_OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
+ emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input,
+ swizzle1(params,X), swizzle1(params,Y));
+ emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
+ emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
break;
}
case FOG_EXP:
- emit_op1(p, VP_OPCODE_ABS, tmp, 0, input);
- emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, swizzle1(params,X));
- emit_op2(p, VP_OPCODE_POW, fog, WRITEMASK_X,
- register_const1f(p, M_E), negate(tmp));
+ emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input,
+ swizzle1(params,Z));
+ emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
break;
case FOG_EXP2:
- emit_op2(p, VP_OPCODE_MUL, tmp, 0, input, swizzle1(params,X));
- emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, tmp);
- emit_op2(p, VP_OPCODE_POW, fog, WRITEMASK_X,
- register_const1f(p, M_E), negate(tmp));
+ emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W));
+ emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp);
+ emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
break;
}
-
+
release_temp(p, tmp);
}
else {
/* results = incoming fog coords (compute fog per-fragment later)
*
* KW: Is it really necessary to do anything in this case?
+ * BP: Yes, we always need to compute the absolute value, unless
+ * we want to push that down into the fragment program...
*/
- emit_op1(p, VP_OPCODE_MOV, fog, WRITEMASK_X, input);
+ GLboolean useabs = GL_TRUE;
+ emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, WRITEMASK_X, input);
}
}
struct ureg tmp = get_temp(p);
/* n.u */
- emit_op2(p, VP_OPCODE_DP3, tmp, 0, normal, eye_hat);
+ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
/* 2n.u */
- emit_op2(p, VP_OPCODE_ADD, tmp, 0, tmp, tmp);
+ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
/* (-2n.u)n + u */
- emit_op3(p, VP_OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
+ emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
+
+ release_temp(p, tmp);
}
static void build_sphere_texgen( struct tnl_program *p,
*/
/* n.u */
- emit_op2(p, VP_OPCODE_DP3, tmp, 0, normal, eye_hat);
+ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
/* 2n.u */
- emit_op2(p, VP_OPCODE_ADD, tmp, 0, tmp, tmp);
+ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
/* (-2n.u)n + u */
- emit_op3(p, VP_OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
+ emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
/* r + 0,0,1 */
- emit_op2(p, VP_OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
+ emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
/* rx^2 + ry^2 + (rz+1)^2 */
- emit_op2(p, VP_OPCODE_DP3, tmp, 0, tmp, tmp);
+ emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);
/* 2/m */
- emit_op1(p, VP_OPCODE_RSQ, tmp, 0, tmp);
+ emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
/* 1/m */
- emit_op2(p, VP_OPCODE_MUL, inv_m, 0, tmp, half);
+ emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);
/* r/m + 1/2 */
- emit_op3(p, VP_OPCODE_MAD, dest, writemask, r, inv_m, half);
+ emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half);
release_temp(p, tmp);
release_temp(p, r);
GLuint i, j;
for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
- GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
- if (p->state->unit[i].texgen_enabled || texmat_enabled) {
+ if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i)))
+ continue;
+
+ if (p->state->unit[i].texgen_enabled ||
+ p->state->unit[i].texmat_enabled) {
+
+ GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
struct ureg out_texgen = undef;
register_param3(p, STATE_TEXGEN, i,
STATE_TEXGEN_OBJECT_S + j);
- emit_op2(p, VP_OPCODE_DP4, out_texgen, WRITEMASK_X << j,
+ emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
obj, plane );
break;
}
register_param3(p, STATE_TEXGEN, i,
STATE_TEXGEN_EYE_S + j);
- emit_op2(p, VP_OPCODE_DP4, out_texgen, WRITEMASK_X << j,
+ emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
eye, plane );
break;
}
if (normal_mask) {
struct ureg normal = get_eye_normal(p);
- emit_op1(p, VP_OPCODE_MOV, out_texgen, normal_mask, normal );
+ emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal );
}
if (copy_mask) {
struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i);
- emit_op1(p, VP_OPCODE_MOV, out_texgen, copy_mask, in );
+ emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in );
}
}
out_texgen :
register_input(p, VERT_ATTRIB_TEX0+i));
if (PREFER_DP4) {
- register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i,
- 0, 3, STATE_MATRIX, texmat );
+ register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
+ 0, texmat );
emit_matrix_transform_vec4( p, out, texmat, in );
}
else {
- register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i,
- 0, 3, STATE_MATRIX_TRANSPOSE, texmat );
+ register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
+ STATE_MATRIX_TRANSPOSE, texmat );
emit_transpose_matrix_transform_vec4( p, out, texmat, in );
}
}
release_temps(p);
}
- else if (p->state->unit[i].texunit_really_enabled) {
- /* KW: _ReallyEnabled isn't sufficient? Need to know whether
- * this texture unit is referenced by the fragment shader.
- */
+ else {
emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
}
}
}
-/* Seems like it could be tighter:
- */
static void build_pointsize( struct tnl_program *p )
{
struct ureg eye = get_eye_position(p);
struct ureg out = register_output(p, VERT_RESULT_PSIZ);
struct ureg ut = get_temp(p);
- /* 1, -Z, Z * Z, 1 */
- emit_op1(p, VP_OPCODE_MOV, ut, 0, swizzle1(get_identity_param(p), W));
- emit_op2(p, VP_OPCODE_MUL, ut, WRITEMASK_YZ, ut, negate(swizzle1(eye, Z)));
- emit_op2(p, VP_OPCODE_MUL, ut, WRITEMASK_Z, ut, negate(swizzle1(eye, Z)));
-
-
- /* p1 + p2 * dist + p3 * dist * dist, 0 */
- emit_op2(p, VP_OPCODE_DP3, ut, 0, ut, state_attenuation);
-
- /* 1 / factor */
- emit_op1(p, VP_OPCODE_RCP, ut, 0, ut );
-
- /* out = pointSize / factor */
- emit_op2(p, VP_OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
+ /* dist = |eyez| */
+ emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z));
+ /* p1 + dist * (p2 + dist * p3); */
+ emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
+ swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y));
+ emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
+ ut, swizzle1(state_attenuation, X));
+
+ /* 1 / sqrt(factor) */
+ emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut );
+
+#if 1
+ /* out = pointSize / sqrt(factor) */
+ emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
+#else
+ /* not sure, might make sense to do clamping here,
+ but it's not done in t_vb_points neither */
+ emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size);
+ emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y));
+ emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z));
+#endif
release_temp(p, ut);
}
/* Lighting calculations:
*/
- if (p->state->light_global_enabled)
- build_lighting(p);
- else
- emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
+ if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) {
+ if (p->state->light_global_enabled)
+ build_lighting(p);
+ else {
+ if (p->state->fragprog_inputs_read & FRAG_BIT_COL0)
+ emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
+
+ if (p->state->fragprog_inputs_read & FRAG_BIT_COL1)
+ emit_passthrough(p, VERT_ATTRIB_COLOR1, VERT_RESULT_COL1);
+ }
+ }
- if (p->state->fog_enabled)
+ if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) ||
+ p->state->fog_mode != FOG_NONE)
build_fog(p);
- if (p->state->texture_enabled_global)
+ if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
build_texture_transform(p);
if (p->state->point_attenuated)
/* Finish up:
*/
- emit_op1(p, VP_OPCODE_END, undef, 0, undef);
+ emit_op1(p, OPCODE_END, undef, 0, undef);
/* Disassemble:
*/
static void
create_new_program( const struct state_key *key,
- struct vertex_program *program,
+ struct gl_vertex_program *program,
GLuint max_temps)
{
struct tnl_program p;
else
p.temp_reserved = ~((1<<max_temps)-1);
- p.program->Instructions = MALLOC(sizeof(struct vp_instruction) * MAX_INSN);
- p.program->Base.String = 0;
+ p.program->Base.Instructions = _mesa_alloc_instructions(MAX_INSN);
+ p.program->Base.String = NULL;
p.program->Base.NumInstructions =
p.program->Base.NumTemporaries =
p.program->Base.NumParameters =
p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
- p.program->Parameters = _mesa_new_parameter_list();
- p.program->InputsRead = 0;
- p.program->OutputsWritten = 0;
+ p.program->Base.Parameters = _mesa_new_parameter_list();
+ p.program->Base.InputsRead = 0;
+ p.program->Base.OutputsWritten = 0;
build_tnl_program( &p );
}
GLuint size, i;
size = cache->size * 3;
- items = MALLOC(size * sizeof(*items));
+ items = (struct tnl_cache_item**) _mesa_malloc(size * sizeof(*items));
_mesa_memset(items, 0, size * sizeof(*items));
for (i = 0; i < cache->size; i++)
void *key,
void *data )
{
- struct tnl_cache_item *c = MALLOC(sizeof(*c));
+ struct tnl_cache_item *c = (struct tnl_cache_item*) _mesa_malloc(sizeof(*c));
c->hash = hash;
c->key = key;
c->data = data;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct state_key *key;
GLuint hash;
+ const struct gl_vertex_program *prev = ctx->VertexProgram._Current;
- if (ctx->VertexProgram._Enabled)
- return;
-
- /* Grab all the relevent state and put it in a single structure:
- */
- key = make_state_key(ctx);
- hash = hash_key(key);
-
- if (tnl->vp_cache == NULL) {
- tnl->vp_cache = MALLOC(sizeof(*tnl->vp_cache));
- tnl->vp_cache->size = 5;
- tnl->vp_cache->n_items = 0;
- tnl->vp_cache->items = MALLOC(tnl->vp_cache->size *
- sizeof(*tnl->vp_cache->items));
- _mesa_memset(tnl->vp_cache->items, 0, tnl->vp_cache->size *
- sizeof(*tnl->vp_cache->items));
- }
+ if (!ctx->VertexProgram._Current ||
+ ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
+ /* Grab all the relevent state and put it in a single structure:
+ */
+ key = make_state_key(ctx);
+ hash = hash_key(key);
- /* Look for an already-prepared program for this state:
- */
- ctx->_TnlProgram = (struct vertex_program *)
- search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
+ /* Look for an already-prepared program for this state:
+ */
+ ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
+ search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
- /* OK, we'll have to build a new one:
- */
- if (!ctx->_TnlProgram) {
- if (0)
- _mesa_printf("Build new TNL program\n");
+ /* OK, we'll have to build a new one:
+ */
+ if (!ctx->VertexProgram._TnlProgram) {
+ if (0)
+ _mesa_printf("Build new TNL program\n");
+
+ ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
- ctx->_TnlProgram = (struct vertex_program *)
- ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ create_new_program( key, ctx->VertexProgram._TnlProgram,
+ ctx->Const.VertexProgram.MaxTemps );
- create_new_program( key, ctx->_TnlProgram,
- ctx->Const.MaxVertexProgramTemps );
+ if (ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,
+ &ctx->VertexProgram._TnlProgram->Base );
- cache_item(tnl->vp_cache, hash, key, ctx->_TnlProgram );
- }
- else {
- FREE(key);
- if (0)
- _mesa_printf("Found existing TNL program for key %x\n", hash);
+ cache_item(tnl->vp_cache, hash, key, ctx->VertexProgram._TnlProgram );
+ }
+ else {
+ FREE(key);
+ if (0)
+ _mesa_printf("Found existing TNL program for key %x\n", hash);
+ }
+ ctx->VertexProgram._Current = ctx->VertexProgram._TnlProgram;
}
- /* Need a BindProgram callback for the driver?
+ /* Tell the driver about the change. Could define a new target for
+ * this?
*/
+ if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ (struct gl_program *) ctx->VertexProgram._Current);
+ }
}
+void _tnl_ProgramCacheInit( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ tnl->vp_cache = (struct tnl_cache *) MALLOC(sizeof(*tnl->vp_cache));
+ tnl->vp_cache->size = 17;
+ tnl->vp_cache->n_items = 0;
+ tnl->vp_cache->items = (struct tnl_cache_item**)
+ _mesa_calloc(tnl->vp_cache->size * sizeof(*tnl->vp_cache->items));
+}
void _tnl_ProgramCacheDestroy( GLcontext *ctx )
{