X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fatifragshader.c;h=44f6bb46484293c5f44fed89b52e09593ccf1a9d;hb=0ca266025ab309d538ed8c804cb46d2945c6a547;hp=550f50b7a00fbe5fabbb8cfb6b8dc38acb560a74;hpb=afe125e0a18ac3886c45c7e6b02b122fb2d327b5;p=mesa.git diff --git a/src/mesa/main/atifragshader.c b/src/mesa/main/atifragshader.c index 550f50b7a00..44f6bb46484 100644 --- a/src/mesa/main/atifragshader.c +++ b/src/mesa/main/atifragshader.c @@ -24,45 +24,24 @@ #include "main/glheader.h" #include "main/context.h" #include "main/hash.h" -#include "main/imports.h" + #include "main/macros.h" #include "main/enums.h" #include "main/mtypes.h" -#include "main/dispatch.h" #include "main/atifragshader.h" - -#if FEATURE_ATI_fragment_shader +#include "program/program.h" +#include "util/u_memory.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. */ struct ati_fragment_shader * -_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id) +_mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id) { struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader); (void) ctx; @@ -78,38 +57,26 @@ _mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id) * Delete the given ati fragment shader */ void -_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s) +_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++) { - if (s->Instructions[i]) - free(s->Instructions[i]); - if (s->SetupInst[i]) - free(s->SetupInst[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; } } @@ -143,7 +110,7 @@ create_dst_mod_str(GLuint mod) return ret_str; } -static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", +static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" }; static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, @@ -155,30 +122,30 @@ static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, char *op_name; 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); @@ -189,23 +156,34 @@ static int check_arith_arg(struct ati_fragment_shader *curProg, _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 is SECONDARY_INTERPOLATOR_ATI + * and is ALPHA, or by AlphaFragmentOp[1..3]ATI if + * is SECONDARY_INTERPOLATOR_ATI and 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) { @@ -223,11 +201,15 @@ _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; } @@ -279,12 +261,9 @@ _mesa_BindFragmentShaderATI(GLuint id) /* 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 @@ -316,7 +295,7 @@ _mesa_DeleteFragmentShaderATI(GLuint id) if (prog) { prog->RefCount--; if (prog->RefCount <= 0) { - free(prog); + _mesa_delete_ati_fragment_shader(ctx, prog); } } } @@ -340,23 +319,21 @@ _mesa_BeginFragmentShaderATI(void) (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]) - free(ctx->ATIFragmentShader.Current->Instructions[i]); - if (ctx->ATIFragmentShader.Current->SetupInst[i]) - free(ctx->ATIFragmentShader.Current->SetupInst[i]); + free(ctx->ATIFragmentShader.Current->Instructions[i]); + 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] = - (struct atifs_instruction *) - 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] = - (struct atifs_setupinst *) - 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 (?) */ @@ -372,6 +349,9 @@ _mesa_BeginFragmentShaderATI(void) 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 @@ -410,7 +390,7 @@ _mesa_EndFragmentShaderATI(void) 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, @@ -419,8 +399,8 @@ _mesa_EndFragmentShaderATI(void) 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, @@ -429,7 +409,17 @@ _mesa_EndFragmentShaderATI(void) } #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, @@ -443,18 +433,17 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) 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; } @@ -469,7 +458,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) _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; } @@ -492,8 +481,10 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) } } - curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); - new_tex_inst(curProg); + 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); /* add the instructions */ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; @@ -503,9 +494,9 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) 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 } @@ -515,18 +506,17 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) 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; } @@ -542,7 +532,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) _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; } @@ -565,8 +555,10 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) } } - curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); - new_tex_inst(curProg); + 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); /* add the instructions */ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; @@ -576,9 +568,9 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) 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 } @@ -594,34 +586,36 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, 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)) { @@ -630,7 +624,7 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, } 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; @@ -640,7 +634,7 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, _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)) || @@ -649,22 +643,29 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, 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 is DOT4_ATI and is SECONDARY_INTERPOLATOR_ATI and + * 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) && @@ -678,6 +679,16 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, /* 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; @@ -790,5 +801,3 @@ _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value) COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value); } } - -#endif /* FEATURE_ATI_fragment_shader */