#include "main/glheader.h"
#include "main/context.h"
#include "main/hash.h"
-#include "main/imports.h"
+#include "util/imports.h"
#include "main/macros.h"
-#include "main/mfeatures.h"
#include "main/enums.h"
#include "main/mtypes.h"
-#include "main/dispatch.h"
#include "main/atifragshader.h"
+#include "program/program.h"
#define MESA_DEBUG_ATI_FS 0
static struct ati_fragment_shader DummyShader;
-void
-_mesa_init_ati_fragment_shader_dispatch(struct _glapi_table *disp)
-{
- SET_GenFragmentShadersATI(disp, _mesa_GenFragmentShadersATI);
- SET_BindFragmentShaderATI(disp, _mesa_BindFragmentShaderATI);
- SET_DeleteFragmentShaderATI(disp, _mesa_DeleteFragmentShaderATI);
- SET_BeginFragmentShaderATI(disp, _mesa_BeginFragmentShaderATI);
- SET_EndFragmentShaderATI(disp, _mesa_EndFragmentShaderATI);
- SET_PassTexCoordATI(disp, _mesa_PassTexCoordATI);
- SET_SampleMapATI(disp, _mesa_SampleMapATI);
- SET_ColorFragmentOp1ATI(disp, _mesa_ColorFragmentOp1ATI);
- SET_ColorFragmentOp2ATI(disp, _mesa_ColorFragmentOp2ATI);
- SET_ColorFragmentOp3ATI(disp, _mesa_ColorFragmentOp3ATI);
- SET_AlphaFragmentOp1ATI(disp, _mesa_AlphaFragmentOp1ATI);
- SET_AlphaFragmentOp2ATI(disp, _mesa_AlphaFragmentOp2ATI);
- SET_AlphaFragmentOp3ATI(disp, _mesa_AlphaFragmentOp3ATI);
- SET_SetFragmentShaderConstantATI(disp, _mesa_SetFragmentShaderConstantATI);
-}
-
-
/**
* Allocate and initialize a new ATI fragment shader object.
*/
_mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s)
{
GLuint i;
+
+ if (s == &DummyShader)
+ return;
+
for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
free(s->Instructions[i]);
free(s->SetupInst[i]);
}
+ _mesa_reference_program(ctx, &s->Program, NULL);
free(s);
}
-
-static void
-new_arith_inst(struct ati_fragment_shader *prog)
-{
-/* set "default" instruction as not all may get defined.
- there is no specified way to express a nop with ati fragment shaders we use
- GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
- prog->numArithInstr[prog->cur_pass >> 1]++;
-}
-
-static void
-new_tex_inst(struct ati_fragment_shader *prog)
-{
-}
-
static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
{
if (optype == curProg->last_optype) {
- curProg->last_optype = 1;
+ curProg->last_optype = ATI_FRAGMENT_SHADER_ALPHA_OP;
}
}
op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
- fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
- _mesa_lookup_enum_by_nr(dst));
- if (!optype)
+ fprintf(stderr, "%s(%s, %s", op_name, _mesa_enum_to_string(op),
+ _mesa_enum_to_string(dst));
+ if (optype == ATI_FRAGMENT_SHADER_COLOR_OP)
fprintf(stderr, ", %d", dstMask);
fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
- fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
- _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
+ fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg1),
+ _mesa_enum_to_string(arg1Rep), arg1Mod);
if (arg_count>1)
- fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
- _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
+ fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg2),
+ _mesa_enum_to_string(arg2Rep), arg2Mod);
if (arg_count>2)
- fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
- _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
+ fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg3),
+ _mesa_enum_to_string(arg3Rep), arg3Mod);
fprintf(stderr,")\n");
}
#endif
-static int check_arith_arg(struct ati_fragment_shader *curProg,
- GLuint optype, GLuint arg, GLuint argRep)
+static int
+check_arith_arg(GLuint optype, GLuint arg, GLuint argRep)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
return 0;
}
- if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
- ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
- return 0;
- }
- if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
- ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
- return 0;
- }
- if ((curProg->cur_pass == 1) &&
- ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
- curProg->interpinp1 = GL_TRUE;
+ /* The ATI_fragment_shader spec says:
+ *
+ * The error INVALID_OPERATION is generated by
+ * ColorFragmentOp[1..3]ATI if <argN> is SECONDARY_INTERPOLATOR_ATI
+ * and <argNRep> is ALPHA, or by AlphaFragmentOp[1..3]ATI if <argN>
+ * is SECONDARY_INTERPOLATOR_ATI and <argNRep> is ALPHA or NONE, ...
+ */
+ if (arg == GL_SECONDARY_INTERPOLATOR_ATI) {
+ if (optype == ATI_FRAGMENT_SHADER_COLOR_OP && argRep == GL_ALPHA) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "CFragmentOpATI(sec_interp)");
+ return 0;
+ } else if (optype == ATI_FRAGMENT_SHADER_ALPHA_OP &&
+ (argRep == GL_ALPHA || argRep == GL_NONE)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(sec_interp)");
+ return 0;
+ }
}
return 1;
}
+static GLboolean
+check_arg_color(GLubyte pass, GLuint arg)
+{
+ if (pass == 1 && (arg == GL_PRIMARY_COLOR_ARB || arg == GL_SECONDARY_INTERPOLATOR_ATI))
+ return GL_TRUE;
+ return GL_FALSE;
+}
+
GLuint GLAPIENTRY
_mesa_GenFragmentShadersATI(GLuint range)
{
return 0;
}
+ _mesa_HashLockMutex(ctx->Shared->ATIShaders);
+
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
for (i = 0; i < range; i++) {
- _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
+ _mesa_HashInsertLocked(ctx->Shared->ATIShaders, first + i, &DummyShader);
}
+ _mesa_HashUnlockMutex(ctx->Shared->ATIShaders);
+
return first;
}
/* do actual bind */
ctx->ATIFragmentShader.Current = newProg;
- ASSERT(ctx->ATIFragmentShader.Current);
+ assert(ctx->ATIFragmentShader.Current);
if (newProg)
newProg->RefCount++;
-
- /*if (ctx->Driver.BindProgram)
- ctx->Driver.BindProgram(ctx, target, prog); */
}
void GLAPIENTRY
if (prog) {
prog->RefCount--;
if (prog->RefCount <= 0) {
- assert(prog != &DummyShader);
- free(prog);
+ _mesa_delete_ati_fragment_shader(ctx, prog);
}
}
}
free(ctx->ATIFragmentShader.Current->SetupInst[i]);
}
+ _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL);
+
/* malloc the instructions here - not sure if the best place but its
a start */
for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
ctx->ATIFragmentShader.Current->Instructions[i] =
- calloc(1, sizeof(struct atifs_instruction) *
- (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
+ calloc(sizeof(struct atifs_instruction),
+ MAX_NUM_INSTRUCTIONS_PER_PASS_ATI);
ctx->ATIFragmentShader.Current->SetupInst[i] =
- calloc(1, sizeof(struct atifs_setupinst) *
- (MAX_NUM_FRAGMENT_REGISTERS_ATI));
+ calloc(sizeof(struct atifs_setupinst),
+ MAX_NUM_FRAGMENT_REGISTERS_ATI);
}
/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
ctx->ATIFragmentShader.Current->swizzlerq = 0;
ctx->ATIFragmentShader.Compiling = 1;
+#if MESA_DEBUG_ATI_FS
+ _mesa_debug(ctx, "%s %u\n", __func__, ctx->ATIFragmentShader.Current->Id);
+#endif
}
void GLAPIENTRY
for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
GLuint op = curProg->SetupInst[j][i].Opcode;
- const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
+ const char *op_enum = op > 5 ? _mesa_enum_to_string(op) : "0";
GLuint src = curProg->SetupInst[j][i].src;
GLuint swizzle = curProg->SetupInst[j][i].swizzle;
fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
for (i = 0; i < curProg->numArithInstr[j]; i++) {
GLuint op0 = curProg->Instructions[j][i].Opcode[0];
GLuint op1 = curProg->Instructions[j][i].Opcode[1];
- const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
- const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
+ const char *op0_enum = op0 > 5 ? _mesa_enum_to_string(op0) : "0";
+ const char *op1_enum = op1 > 5 ? _mesa_enum_to_string(op1) : "0";
GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
}
#endif
- if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) {
+ if (ctx->Driver.NewATIfs) {
+ struct gl_program *prog = ctx->Driver.NewATIfs(ctx,
+ ctx->ATIFragmentShader.Current);
+ _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program,
+ NULL);
+ /* Don't use _mesa_reference_program(), just take ownership */
+ ctx->ATIFragmentShader.Current->Program = prog;
+ }
+
+ if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI,
+ curProg->Program)) {
ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
/* XXX is this the right error? */
_mesa_error(ctx, GL_INVALID_OPERATION,
GET_CURRENT_CONTEXT(ctx);
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
struct atifs_setupinst *curI;
+ GLubyte new_pass = curProg->cur_pass;
if (!ctx->ATIFragmentShader.Compiling) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
return;
}
- if (curProg->cur_pass == 1) {
- match_pair_inst(curProg, 0);
- curProg->cur_pass = 2;
- }
- if ((curProg->cur_pass > 2) ||
- ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
+ if (curProg->cur_pass == 1)
+ new_pass = 2;
+ if ((new_pass > 2) ||
+ ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[new_pass >> 1])) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
return;
}
_mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
return;
}
- if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
+ if ((new_pass == 0) && (coord >= GL_REG_0_ATI)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
return;
}
}
}
+ if (curProg->cur_pass == 1)
+ match_pair_inst(curProg, 0);
+ curProg->cur_pass = new_pass;
curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
- new_tex_inst(curProg);
/* add the instructions */
curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
- _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
- _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
- _mesa_lookup_enum_by_nr(swizzle));
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
+ _mesa_enum_to_string(dst), _mesa_enum_to_string(coord),
+ _mesa_enum_to_string(swizzle));
#endif
}
GET_CURRENT_CONTEXT(ctx);
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
struct atifs_setupinst *curI;
+ GLubyte new_pass = curProg->cur_pass;
if (!ctx->ATIFragmentShader.Compiling) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
return;
}
- if (curProg->cur_pass == 1) {
- match_pair_inst(curProg, 0);
- curProg->cur_pass = 2;
- }
- if ((curProg->cur_pass > 2) ||
- ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
+ if (curProg->cur_pass == 1)
+ new_pass = 2;
+ if ((new_pass > 2) ||
+ ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[new_pass >> 1])) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
return;
}
_mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
return;
}
- if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
+ if ((new_pass == 0) && (interp >= GL_REG_0_ATI)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
return;
}
}
}
+ if (curProg->cur_pass == 1)
+ match_pair_inst(curProg, 0);
+ curProg->cur_pass = new_pass;
curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
- new_tex_inst(curProg);
/* add the instructions */
curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
- _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
- _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
- _mesa_lookup_enum_by_nr(swizzle));
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
+ _mesa_enum_to_string(dst), _mesa_enum_to_string(interp),
+ _mesa_enum_to_string(swizzle));
#endif
}
GLint ci;
struct atifs_instruction *curI;
GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
+ GLubyte new_pass = curProg->cur_pass;
+ GLubyte numArithInstr;
if (!ctx->ATIFragmentShader.Compiling) {
_mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
return;
}
- if (curProg->cur_pass==0)
- curProg->cur_pass=1;
+ if (curProg->cur_pass == 0)
+ new_pass = 1;
+ else if (curProg->cur_pass == 2)
+ new_pass = 3;
- else if (curProg->cur_pass==2)
- curProg->cur_pass=3;
+ numArithInstr = curProg->numArithInstr[new_pass >> 1];
- /* decide whether this is a new instruction or not ... all color instructions are new,
- and alpha instructions might also be new if there was no preceding color inst */
- if ((optype == 0) || (curProg->last_optype == optype)) {
- if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
+ /* Decide whether this is a new instruction or not. All color instructions
+ * are new, and alpha instructions might also be new if there was no
+ * preceding color inst. This may also be the first inst of the pass
+ */
+ if (optype == ATI_FRAGMENT_SHADER_COLOR_OP ||
+ curProg->last_optype == optype ||
+ curProg->numArithInstr[new_pass >> 1] == 0) {
+ if (curProg->numArithInstr[new_pass >> 1] > 7) {
_mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
return;
}
- /* easier to do that here slight side effect invalid instr will still be inserted as nops */
- match_pair_inst(curProg, optype);
- new_arith_inst(curProg);
+ numArithInstr++;
}
- curProg->last_optype = optype;
- ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
-
- /* add the instructions */
- curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
+ ci = numArithInstr - 1;
+ curI = &curProg->Instructions[new_pass >> 1][ci];
/* error checking */
if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
}
if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
(modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
- (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
+ (modtemp != GL_HALF_BIT_ATI) && (modtemp != GL_QUARTER_BIT_ATI) &&
(modtemp != GL_EIGHTH_BIT_ATI)) {
_mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
return;
_mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
return;
}
- if (optype == 1) {
+ if (optype == ATI_FRAGMENT_SHADER_ALPHA_OP) {
if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
return;
}
}
- if ((op == GL_DOT4_ATI) &&
- (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
- (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
+ /* The ATI_fragment_shader spec says:
+ *
+ * The error INVALID_OPERATION is generated by... ColorFragmentOp2ATI
+ * if <op> is DOT4_ATI and <argN> is SECONDARY_INTERPOLATOR_ATI and
+ * <argNRep> is ALPHA or NONE.
+ */
+ if (optype == ATI_FRAGMENT_SHADER_COLOR_OP && op == GL_DOT4_ATI &&
+ ((arg1 == GL_SECONDARY_INTERPOLATOR_ATI && (arg1Rep == GL_ALPHA || arg1Rep == GL_NONE)) ||
+ (arg2 == GL_SECONDARY_INTERPOLATOR_ATI && (arg2Rep == GL_ALPHA || arg2Rep == GL_NONE)))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interpDOT4)");
+ return;
}
- if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
+ if (!check_arith_arg(optype, arg1, arg1Rep)) {
return;
}
if (arg2) {
- if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
+ if (!check_arith_arg(optype, arg2, arg2Rep)) {
return;
}
}
if (arg3) {
- if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
+ if (!check_arith_arg(optype, arg3, arg3Rep)) {
return;
}
if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
/* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
+ curProg->interpinp1 |= check_arg_color(new_pass, arg1);
+ if (arg2)
+ curProg->interpinp1 |= check_arg_color(new_pass, arg2);
+ if (arg3)
+ curProg->interpinp1 |= check_arg_color(new_pass, arg3);
+
+ curProg->numArithInstr[new_pass >> 1] = numArithInstr;
+ curProg->last_optype = optype;
+ curProg->cur_pass = new_pass;
+
curI->Opcode[optype] = op;
curI->SrcReg[optype][0].Index = arg1;
curI->SrcReg[optype][0].argRep = arg1Rep;