#define MESA_DEBUG_ATI_FS 0
-extern struct program _mesa_DummyProgram;
+static struct ati_fragment_shader DummyShader;
+
+
+/**
+ * Allocate and initialize a new ATI fragment shader object.
+ */
+struct ati_fragment_shader *
+_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
+{
+ struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
+ (void) ctx;
+ if (s) {
+ s->Id = id;
+ s->RefCount = 1;
+ }
+ return s;
+}
+
+
+/**
+ * Delete the given ati fragment shader
+ */
+void
+_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
+{
+ GLuint i;
+ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+ if (s->Instructions[i])
+ _mesa_free(s->Instructions[i]);
+ if (s->SetupInst[i])
+ _mesa_free(s->SetupInst[i]);
+ }
+ _mesa_free(s);
+}
+
+
static void
-new_inst(struct ati_fragment_shader *prog)
+new_arith_inst(struct ati_fragment_shader *prog)
{
- prog->Base.NumInstructions++;
+/* 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;
+ }
}
#if MESA_DEBUG_ATI_FS
}
#endif
+static int check_arith_arg(struct ati_fragment_shader *curProg,
+ GLuint optype, GLuint arg, GLuint argRep)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
+ ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
+ (arg != GL_ZERO) && (arg != GL_ONE) &&
+ (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
+ _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;
+ }
+ return 1;
+}
+
GLuint GLAPIENTRY
_mesa_GenFragmentShadersATI(GLuint range)
{
GLuint i;
GET_CURRENT_CONTEXT(ctx);
- first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, range);
+ if (range == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
+ return 0;
+ }
+
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
+ return 0;
+ }
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
for (i = 0; i < range; i++) {
- _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
+ _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
}
return first;
void GLAPIENTRY
_mesa_BindFragmentShaderATI(GLuint id)
{
- struct program *prog;
GET_CURRENT_CONTEXT(ctx);
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ struct ati_fragment_shader *newProg;
+
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
+ return;
+ }
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- if (curProg->Base.Id == id) {
+ if (curProg->Id == id) {
return;
}
- if (curProg->Base.Id != 0) {
- curProg->Base.RefCount--;
- if (curProg->Base.RefCount <= 0) {
- _mesa_HashRemove(ctx->Shared->Programs, id);
+ /* unbind current */
+ if (curProg->Id != 0) {
+ curProg->RefCount--;
+ if (curProg->RefCount <= 0) {
+ _mesa_HashRemove(ctx->Shared->ATIShaders, id);
}
}
- /* Go bind */
+ /* find new shader */
if (id == 0) {
- prog = ctx->Shared->DefaultFragmentShader;
+ newProg = ctx->Shared->DefaultFragmentShader;
}
else {
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
- if (!prog || prog == &_mesa_DummyProgram) {
+ newProg = (struct ati_fragment_shader *)
+ _mesa_HashLookup(ctx->Shared->ATIShaders, id);
+ if (!newProg || newProg == &DummyShader) {
/* allocate a new program now */
- prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_SHADER_ATI, id);
- if (!prog) {
+ newProg = _mesa_new_ati_fragment_shader(ctx, id);
+ if (!newProg) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
return;
}
- _mesa_HashInsert(ctx->Shared->Programs, id, prog);
+ _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
}
}
/* do actual bind */
- ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) prog;
+ ctx->ATIFragmentShader.Current = newProg;
ASSERT(ctx->ATIFragmentShader.Current);
- if (prog)
- prog->RefCount++;
+ if (newProg)
+ newProg->RefCount++;
/*if (ctx->Driver.BindProgram)
ctx->Driver.BindProgram(ctx, target, prog); */
{
GET_CURRENT_CONTEXT(ctx);
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
+ return;
+ }
+
if (id != 0) {
- struct program *prog = (struct program *)
- _mesa_HashLookup(ctx->Shared->Programs, id);
- if (prog == &_mesa_DummyProgram) {
- _mesa_HashRemove(ctx->Shared->Programs, id);
+ struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
+ _mesa_HashLookup(ctx->Shared->ATIShaders, id);
+ if (prog == &DummyShader) {
+ _mesa_HashRemove(ctx->Shared->ATIShaders, id);
}
else if (prog) {
if (ctx->ATIFragmentShader.Current &&
- ctx->ATIFragmentShader.Current->Base.Id == id) {
+ ctx->ATIFragmentShader.Current->Id == id) {
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
_mesa_BindFragmentShaderATI(0);
}
}
- if (!prog->DeletePending) {
- prog->DeletePending = GL_TRUE;
- prog->RefCount--;
- }
+
+ /* The ID is immediately available for re-use now */
+ _mesa_HashRemove(ctx->Shared->ATIShaders, id);
+ prog->RefCount--;
if (prog->RefCount <= 0) {
- _mesa_HashRemove(ctx->Shared->Programs, id);
- ctx->Driver.DeleteProgram(ctx, prog);
+ _mesa_free(prog);
}
}
}
+
void GLAPIENTRY
_mesa_BeginFragmentShaderATI(void)
{
+ GLint i;
GET_CURRENT_CONTEXT(ctx);
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ /* if the shader was already defined free instructions and get new ones
+ (or, could use the same mem but would need to reinitialize) */
+ /* no idea if it's allowed to redefine a shader */
+ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+ if (ctx->ATIFragmentShader.Current->Instructions[i])
+ _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
+ if (ctx->ATIFragmentShader.Current->SetupInst[i])
+ _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
+ }
+
/* malloc the instructions here - not sure if the best place but its
a start */
- ctx->ATIFragmentShader.Current->Instructions =
- (struct atifs_instruction *)
- _mesa_calloc(sizeof(struct atifs_instruction) * MAX_NUM_PASSES_ATI *
- MAX_NUM_INSTRUCTIONS_PER_PASS_ATI * 2);
+ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+ ctx->ATIFragmentShader.Current->Instructions[i] =
+ (struct atifs_instruction *)
+ _mesa_calloc(sizeof(struct atifs_instruction) *
+ (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
+ ctx->ATIFragmentShader.Current->SetupInst[i] =
+ (struct atifs_setupinst *)
+ _mesa_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->LocalConstDef = 0;
+ ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
+ ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
+ ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
+ ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
+ ctx->ATIFragmentShader.Current->NumPasses = 0;
ctx->ATIFragmentShader.Current->cur_pass = 0;
+ ctx->ATIFragmentShader.Current->last_optype = 0;
+ ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
+ ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
+ ctx->ATIFragmentShader.Current->swizzlerq = 0;
ctx->ATIFragmentShader.Compiling = 1;
}
_mesa_EndFragmentShaderATI(void)
{
GET_CURRENT_CONTEXT(ctx);
-#if MESA_DEBUG_ATI_FS
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
- GLint i;
+#if MESA_DEBUG_ATI_FS
+ GLint i, j;
#endif
- ctx->ATIFragmentShader.Compiling = 0;
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
+ return;
+ }
+ if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
+ /* according to spec, DON'T return here */
+ }
+ match_pair_inst(curProg, 0);
+ ctx->ATIFragmentShader.Compiling = 0;
+ ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
+ if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
+ (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
+ }
+ if (ctx->ATIFragmentShader.Current->cur_pass > 1)
+ ctx->ATIFragmentShader.Current->NumPasses = 2;
+ else ctx->ATIFragmentShader.Current->NumPasses = 1;
+ ctx->ATIFragmentShader.Current->cur_pass=0;
#if MESA_DEBUG_ATI_FS
- for (i = 0; i < curProg->Base.NumInstructions; i++) {
- GLuint op0 = curProg->Instructions[i].Opcode[0];
- GLuint op1 = curProg->Instructions[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";
- GLuint count0 = curProg->Instructions[i].ArgCount[0];
- GLuint count1 = curProg->Instructions[i].ArgCount[1];
-
- fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
+ 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";
+ 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,
+ swizzle);
+ }
+ 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";
+ 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,
op1, op1_enum, count1);
+ }
}
#endif
+ if (ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL );
}
void GLAPIENTRY
{
GET_CURRENT_CONTEXT(ctx);
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
- GLint ci;
- struct atifs_instruction *curI;
+ struct atifs_setupinst *curI;
+
+ 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])) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
+ return;
+ }
+ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
+ ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
+ return;
+ }
+ if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
+ ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
+ ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
+ return;
+ }
+ if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
+ return;
+ }
+ if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
+ return;
+ }
+ if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
+ return;
+ }
+ if (coord <= GL_TEXTURE7_ARB) {
+ GLuint tmp = coord - GL_TEXTURE0_ARB;
+ if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
+ (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
+ return;
+ } else {
+ curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
+ }
+ }
- new_inst(curProg);
- ci = curProg->Base.NumInstructions - 1;
- /* some validation
- if ((swizzle != GL_SWIZZLE_STR_ATI) ||
- (swizzle != GL_SWIZZLE_STQ_ATI) ||
- (swizzle != GL_SWIZZLE_STR_DR_ATI) ||
- (swizzle != GL_SWIZZLE_STQ_DQ_ATI))
- */
+ curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
+ new_tex_inst(curProg);
/* add the instructions */
- curI = &curProg->Instructions[ci];
+ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
- curI->Opcode[0] = ATI_FRAGMENT_SHADER_PASS_OP;
- curI->DstReg[0].Index = dst;
- curI->SrcReg[0][0].Index = coord;
- curI->DstReg[0].Swizzle = swizzle;
+ curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
+ curI->src = coord;
+ curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
_mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
{
GET_CURRENT_CONTEXT(ctx);
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
- GLint ci;
- struct atifs_instruction *curI;
+ struct atifs_setupinst *curI;
- new_inst(curProg);
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
+ return;
+ }
- ci = curProg->Base.NumInstructions - 1;
- /* add the instructions */
- curI = &curProg->Instructions[ci];
+ 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])) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
+ return;
+ }
+ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
+ ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
+ return;
+ }
+ if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
+ ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
+ ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
+ /* is this texture5 or texture7? spec is a bit unclear there */
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
+ return;
+ }
+ if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
+ return;
+ }
+ if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
+ return;
+ }
+ if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
+ return;
+ }
+ if (interp <= GL_TEXTURE7_ARB) {
+ GLuint tmp = interp - GL_TEXTURE0_ARB;
+ if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
+ (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
+ return;
+ } else {
+ curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
+ }
+ }
- curI->Opcode[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP;
- curI->DstReg[0].Index = dst;
- curI->DstReg[0].Swizzle = swizzle;
+ 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->SrcReg[0][0].Index = interp;
+ curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
+ curI->src = interp;
+ curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
_mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
GLint ci;
struct atifs_instruction *curI;
+ GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
- /* decide whether this is a new instruction or not ... all color instructions are new */
- if (optype == 0)
- new_inst(curProg);
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
+ return;
+ }
+
+ if (curProg->cur_pass==0)
+ curProg->cur_pass=1;
- ci = curProg->Base.NumInstructions - 1;
+ else if (curProg->cur_pass==2)
+ curProg->cur_pass=3;
+
+ /* 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) {
+ _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);
+ }
+ curProg->last_optype = optype;
+ ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
/* add the instructions */
- curI = &curProg->Instructions[ci];
+ curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
- curI->Opcode[optype] = op;
+ /* error checking */
+ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
+ return;
+ }
+ 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_EIGHTH_BIT_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
+ return;
+ }
+ /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
+ if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
+ return;
+ }
+ if (optype == 1) {
+ 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)) ||
+ ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
+ 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)");
+ }
+
+ if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
+ return;
+ }
+ if (arg2) {
+ if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
+ return;
+ }
+ }
+ if (arg3) {
+ if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
+ return;
+ }
+ if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
+ (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
+ (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
+ (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
+ return;
+ }
+ }
+
+ /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
+ curI->Opcode[optype] = op;
curI->SrcReg[optype][0].Index = arg1;
curI->SrcReg[optype][0].argRep = arg1Rep;
curI->SrcReg[optype][0].argMod = arg1Mod;
curI->DstReg[optype].Index = dst;
curI->DstReg[optype].dstMod = dstMod;
curI->DstReg[optype].dstMask = dstMask;
-
+
#if MESA_DEBUG_ATI_FS
debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
#endif
void GLAPIENTRY
_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
{
+ GLuint dstindex;
GET_CURRENT_CONTEXT(ctx);
- GLuint dstindex = dst - GL_CON_0_ATI;
- struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
- COPY_4V(curProg->Constants[dstindex], value);
+ if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
+ /* spec says nothing about what should happen here but we can't just segfault...*/
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
+ return;
+ }
+
+ dstindex = dst - GL_CON_0_ATI;
+ if (ctx->ATIFragmentShader.Compiling) {
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ COPY_4V(curProg->Constants[dstindex], value);
+ curProg->LocalConstDef |= 1 << dstindex;
+ }
+ else {
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
+ }
}